From: Timo Röhling Date: Tue, 10 Mar 2026 15:40:19 +0000 (+0100) Subject: New upstream version 1.15.1+dfsg X-Git-Tag: archive/raspbian/1.15.1+dfsg-4+rpi1^2^2^2~10^2 X-Git-Url: https://dgit.raspbian.org/%22http://www.example.com/cgi/%22/%22http:/www.example.com/cgi/%22?a=commitdiff_plain;h=7a30adbd79acdefa328bc9b590fcfb11ed15ce7b;p=pcl.git New upstream version 1.15.1+dfsg --- diff --git a/.ci/azure-pipelines/azure-pipelines.yaml b/.ci/azure-pipelines/azure-pipelines.yaml index c69343d5..cdd22762 100644 --- a/.ci/azure-pipelines/azure-pipelines.yaml +++ b/.ci/azure-pipelines/azure-pipelines.yaml @@ -156,7 +156,7 @@ stages: CONTAINER: winx64 PLATFORM: 'x64' ARCHITECTURE: 'x86_amd64' - GENERATOR: '"Visual Studio 16 2019" -A x64' + GENERATOR: '"Visual Studio 17 2022" -A x64' container: $[ variables['CONTAINER'] ] timeoutInMinutes: 0 variables: diff --git a/.ci/azure-pipelines/build/macos.yaml b/.ci/azure-pipelines/build/macos.yaml index 32a7825b..4ad6972d 100644 --- a/.ci/azure-pipelines/build/macos.yaml +++ b/.ci/azure-pipelines/build/macos.yaml @@ -3,7 +3,7 @@ steps: # find the commit hash on a quick non-forced update too fetchDepth: 10 - script: | - brew install cmake pkg-config boost eigen flann glew libusb qhull vtk glew freeglut qt5 libpcap libomp suite-sparse zlib google-benchmark cjson + brew install cmake pkg-config boost eigen flann nanoflann glew libusb qhull vtk glew freeglut qt5 libpcap libomp suite-sparse zlib google-benchmark cjson brew install brewsci/science/openni git clone https://github.com/abseil/googletest.git $GOOGLE_TEST_DIR # the official endpoint changed to abseil/googletest cd $GOOGLE_TEST_DIR && git checkout release-1.8.1 diff --git a/.ci/azure-pipelines/documentation.yaml b/.ci/azure-pipelines/documentation.yaml index 9cfcbfb8..df729de7 100644 --- a/.ci/azure-pipelines/documentation.yaml +++ b/.ci/azure-pipelines/documentation.yaml @@ -2,7 +2,7 @@ jobs: - job: documentation displayName: Generate Documentation pool: - vmImage: 'Ubuntu 20.04' + vmImage: 'ubuntu-22.04' container: doc variables: BUILD_DIR: '$(Agent.BuildDirectory)/build' diff --git a/.ci/azure-pipelines/env.yml b/.ci/azure-pipelines/env.yml index 905f59fd..a1c40c6f 100644 --- a/.ci/azure-pipelines/env.yml +++ b/.ci/azure-pipelines/env.yml @@ -96,7 +96,7 @@ jobs: -DCMAKE_BUILD_TYPE="Release" \ -DPCL_ONLY_CORE_POINT_TYPES=ON \ -DBUILD_io:BOOL=OFF \ - -DBUILD_kdtree:BOOL=OFF && \ + -DBUILD_kdtree:BOOL=OFF $([ $(TAG) = "20.04" ] && (echo " -DCMAKE_CXX_STANDARD=14 -DCMAKE_CUDA_STANDARD=14")) && \ cmake --build . -- -j2' displayName: 'Verify Dockerimage' - task: Docker@2 @@ -109,7 +109,7 @@ jobs: condition: and(eq(variables['Build.Repository.Name'], 'PointCloudLibrary/pcl'), eq(variables['Build.SourceBranch'], 'refs/heads/master')) - job: BuildAndPushWindows - timeoutInMinutes: 360 + timeoutInMinutes: 380 displayName: "Env" pool: vmImage: 'windows-2022' @@ -120,11 +120,13 @@ jobs: TAG: windows2022-x86 GENERATOR: "'Visual Studio 16 2019' -A Win32" VCPKGCOMMIT: f7423ee180c4b7f40d43402c2feb3859161ef625 + CHANNEL_BASE_URL: "https://aka.ms/vs/16/release" Winx64: PLATFORM: x64 TAG: windows2022-x64 - GENERATOR: "'Visual Studio 16 2019' -A x64" + GENERATOR: "'Visual Studio 17 2022' -A x64" VCPKGCOMMIT: master + CHANNEL_BASE_URL: "https://aka.ms/vs/17/release" steps: - task: Docker@2 displayName: "Build docker image" @@ -134,6 +136,7 @@ jobs: --no-cache --build-arg PLATFORM=$(PLATFORM) --build-arg VCPKGCOMMIT=$(VCPKGCOMMIT) + --build-arg CHANNEL_BASE_URL=$(CHANNEL_BASE_URL) -t $(dockerHubID)/env:$(TAG) dockerfile: '$(Build.SourcesDirectory)/.dev/docker/windows/Dockerfile' tags: "$(TAG)" diff --git a/.ci/azure-pipelines/formatting.yaml b/.ci/azure-pipelines/formatting.yaml index 84935030..16ea3ff0 100644 --- a/.ci/azure-pipelines/formatting.yaml +++ b/.ci/azure-pipelines/formatting.yaml @@ -7,7 +7,7 @@ jobs: - checkout: self # find the commit hash on a quick non-forced update too fetchDepth: 10 - - script: ./.dev/format.sh $(which clang-format) . + - script: python ./.dev/format.py . displayName: 'Run clang-format' - script: git diff > formatting.patch displayName: 'Compute diff' diff --git a/.ci/azure-pipelines/tutorials.yaml b/.ci/azure-pipelines/tutorials.yaml index 9317e521..7d94d4fa 100644 --- a/.ci/azure-pipelines/tutorials.yaml +++ b/.ci/azure-pipelines/tutorials.yaml @@ -2,7 +2,7 @@ jobs: - job: tutorials displayName: Building Tutorials pool: - vmImage: 'Ubuntu 20.04' + vmImage: 'ubuntu-22.04' container: env2204 timeoutInMinutes: 0 variables: diff --git a/.ci/azure-pipelines/ubuntu-variety.yaml b/.ci/azure-pipelines/ubuntu-variety.yaml index 997e6272..967c6bc1 100644 --- a/.ci/azure-pipelines/ubuntu-variety.yaml +++ b/.ci/azure-pipelines/ubuntu-variety.yaml @@ -32,9 +32,9 @@ jobs: POSSIBLE_VTK_VERSION=("9") \ POSSIBLE_CMAKE_CXX_STANDARD=("14" "17" "20" "23") \ POSSIBLE_CMAKE_BUILD_TYPE=("None" "Debug" "Release" "RelWithDebInfo" "MinSizeRel") \ - POSSIBLE_COMPILER_PACKAGE=("g++" "g++-11" "g++-12" "g++-13" "g++-14" "clang libomp-dev" "clang-14 libomp-14-dev" "clang-15 libomp-15-dev" "clang-16 libomp-16-dev" "clang-17 libomp-17-dev" "clang-18 libomp-18-dev" "clang-19 libomp-19-dev") \ - POSSIBLE_CMAKE_C_COMPILER=("gcc" "gcc-11" "gcc-12" "gcc-13" "gcc-14" "clang" "clang-14" "clang-15" "clang-16" "clang-17" "clang-18" "clang-19") \ - POSSIBLE_CMAKE_CXX_COMPILER=("g++" "g++-11" "g++-12" "g++-13" "g++-14" "clang++" "clang++-14" "clang++-15" "clang++-16" "clang++-17" "clang++-18" "clang++-19") \ + POSSIBLE_COMPILER_PACKAGE=("g++" "g++-11" "g++-12" "g++-13" "g++-14" "g++-15" "clang libomp-dev" "clang-14 libomp-14-dev" "clang-15 libomp-15-dev" "clang-17 libomp-17-dev" "clang-18 libomp-18-dev" "clang-19 libomp-19-dev" "clang-20 libomp-20-dev") \ + POSSIBLE_CMAKE_C_COMPILER=("gcc" "gcc-11" "gcc-12" "gcc-13" "gcc-14" "gcc-15" "clang" "clang-14" "clang-15" "clang-17" "clang-18" "clang-19" "clang-20") \ + POSSIBLE_CMAKE_CXX_COMPILER=("g++" "g++-11" "g++-12" "g++-13" "g++-14" "g++-15" "clang++" "clang++-14" "clang++-15" "clang++-17" "clang++-18" "clang++-19" "clang++-20") \ CHOSEN_COMPILER=$[RANDOM%${#POSSIBLE_COMPILER_PACKAGE[@]}] \ dockerBuildArgs="--build-arg VTK_VERSION=${POSSIBLE_VTK_VERSION[$[RANDOM%${#POSSIBLE_VTK_VERSION[@]}]]} --build-arg CMAKE_CXX_STANDARD=${POSSIBLE_CMAKE_CXX_STANDARD[$[RANDOM%${#POSSIBLE_CMAKE_CXX_STANDARD[@]}]]} --build-arg CMAKE_BUILD_TYPE=${POSSIBLE_CMAKE_BUILD_TYPE[$[RANDOM%${#POSSIBLE_CMAKE_BUILD_TYPE[@]}]]} --build-arg COMPILER_PACKAGE=\"${POSSIBLE_COMPILER_PACKAGE[$CHOSEN_COMPILER]}\" --build-arg CMAKE_C_COMPILER=${POSSIBLE_CMAKE_C_COMPILER[$CHOSEN_COMPILER]} --build-arg CMAKE_CXX_COMPILER=${POSSIBLE_CMAKE_CXX_COMPILER[$CHOSEN_COMPILER]}" ; \ echo "##vso[task.setvariable variable=dockerBuildArgs]$dockerBuildArgs" diff --git a/.dev/docker/env/Dockerfile b/.dev/docker/env/Dockerfile index a8122a96..d06f58f9 100644 --- a/.dev/docker/env/Dockerfile +++ b/.dev/docker/env/Dockerfile @@ -11,7 +11,7 @@ ARG EIGEN_MINIMUM_VERSION=3.3.7 ARG ENSENSOSDK_VERSION=3.2.489 # See https://github.com/IntelRealSense/librealsense/tags for available tags of releases -ARG REALSENSE_VERSION=2.50.0 +ARG REALSENSE_VERSION=2.56.3 # Check https://packages.ubuntu.com/search?suite=all&arch=any&searchon=names&keywords=libvtk%20qt-dev # for available packages for chosen UBUNTU_VERSION @@ -28,6 +28,7 @@ RUN apt-get update \ build-essential \ clang \ clang-tidy \ + git \ libbenchmark-dev \ libblas-dev \ libboost-serialization-dev \ @@ -54,6 +55,9 @@ RUN apt-get update \ software-properties-common \ wget \ xvfb \ + && if dpkg --compare-versions $(lsb_release -sr) ge 22.04; then \ + apt-get -V install -y libnanoflann-dev ; \ + fi \ && if [ "$USE_LATEST_CMAKE" = true ] ; then \ cmake_ubuntu_version=$(lsb_release -cs) ; \ if ! wget -q --method=HEAD "https://apt.kitware.com/ubuntu/dists/$cmake_ubuntu_version/Release"; then \ diff --git a/.dev/docker/release/Dockerfile b/.dev/docker/release/Dockerfile index 64afbab8..949eb951 100644 --- a/.dev/docker/release/Dockerfile +++ b/.dev/docker/release/Dockerfile @@ -17,6 +17,7 @@ RUN apt update \ libboost-filesystem-dev \ libboost-iostreams-dev \ libboost-system-dev \ + libcjson-dev \ libeigen3-dev \ libflann-dev \ libglew-dev \ diff --git a/.dev/docker/windows/Dockerfile b/.dev/docker/windows/Dockerfile index 902cc9a8..61ff42d4 100644 --- a/.dev/docker/windows/Dockerfile +++ b/.dev/docker/windows/Dockerfile @@ -30,7 +30,8 @@ RUN wget $Env:CHANNEL_BASE_URL/vs_buildtools.exe -OutFile 'C:\TEMP\vs_buildtools "C:\TEMP\VisualStudio.chman", ` "--add", ` "Microsoft.VisualStudio.Workload.VCTools", ` - "Microsoft.Net.Component.4.8.SDK", ` + "Microsoft.Net.Component.4.7.2.SDK", ` + "Microsoft.Net.Component.4.7.2.TargetingPack", ` "Microsoft.VisualStudio.Component.VC.ATLMFC", ` "--includeRecommended" ` -Wait -PassThru; ` @@ -63,11 +64,12 @@ RUN cd .\vcpkg; ` boost-uuid ` boost-cmake ` flann ` + nanoflann ` eigen3 ` qhull ` glew ` freeglut ` - vtk[qt,opengl] ` + vtk[core,qt,opengl] ` gtest ` benchmark ` openni2 ` diff --git a/.dev/format.py b/.dev/format.py new file mode 100644 index 00000000..720abc7a --- /dev/null +++ b/.dev/format.py @@ -0,0 +1,79 @@ +#!/usr/bin/env python3 + +import os +import sys +import subprocess +import argparse + +EXTENSIONS = (".c", ".h", ".cpp", ".hpp", ".cxx", ".hxx", ".cu") +WHITELIST_FILE = os.path.join(".dev", "whitelist.txt") + +def load_whitelist(): + if not os.path.isfile(WHITELIST_FILE): + print(f"Could not find whitelist file at {WHITELIST_FILE}") + sys.exit(167) + with open(WHITELIST_FILE, "r") as f: + return [line.strip() for line in f if line.strip()] + +def is_in_whitelist(file_path, whitelist): + file_path = os.path.normpath(file_path) + for w in whitelist: + w_norm = os.path.normpath(w) + if os.path.commonpath([file_path, w_norm]) == w_norm or file_path.startswith(w_norm + os.sep): + return True + return False + +def find_files(path): + if os.path.isfile(path): + if path.endswith(EXTENSIONS): + yield path + elif os.path.isdir(path): + for root, _, files in os.walk(path): + for file in files: + if file.endswith(EXTENSIONS): + yield os.path.join(root, file) + +def main(): + parser = argparse.ArgumentParser( + description="Format C/C++/CUDA files using clang-format via pipx." + ) + parser.add_argument( + "files", + nargs="+", + help="List of files to check/format, or a single '.' to check all whitelisted files." + ) + args = parser.parse_args() + + whitelist = load_whitelist() + manual_mode = len(args.files) == 1 and args.files[0] == "." + + if manual_mode: + all_files = [] + for rel_path in whitelist: + abs_path = os.path.join(os.getcwd(), rel_path) + all_files.extend(find_files(abs_path)) + else: + all_files = [ + f for f in args.files + if f.endswith(EXTENSIONS) and os.path.isfile(f) and is_in_whitelist(f, whitelist) + ] + + all_files = list(set(all_files)) # Remove duplicates + + if not all_files: + print("No files found to format.") + sys.exit(0) + + check_cmd = ["pipx", "run", "clang-format==14.0.3", "--dry-run", "--Werror", "--style=file"] + all_files + result = subprocess.run(check_cmd, capture_output=True, text=True) + if result.returncode != 0: + format_cmd = ["pipx", "run", "clang-format==14.0.3", "-i", "--style=file"] + all_files + subprocess.run(format_cmd) + if not manual_mode: + sys.exit(1) # Only fail for pre-commit + # In manual mode, just continue and exit 0 + + sys.exit(0) + +if __name__ == "__main__": + main() diff --git a/.dev/format.sh b/.dev/format.sh index e9bf4f33..29bc869f 100755 --- a/.dev/format.sh +++ b/.dev/format.sh @@ -7,9 +7,6 @@ # $ sh /pcl/format.sh `which clang-format` /pcl format() { - # don't use a directory with whitespace - local whitelist="apps/3d_rec_framework apps/in_hand_scanner apps/include apps/modeler apps/src benchmarks 2d geometry ml octree simulation stereo tracking registration gpu/containers gpu/segmentation" - local PCL_DIR="${2}" local formatter="${1}" @@ -18,17 +15,22 @@ format() { exit 166 fi - # check for self if [ ! -f "${PCL_DIR}/.dev/format.sh" ]; then echo "Please ensure that PCL_SOURCE_DIR is passed as the second argument" exit 166 fi - for dir in ${whitelist}; do + local whitelist_file="${PCL_DIR}/.dev/whitelist.txt" + if [ ! -f "${whitelist_file}" ]; then + echo "Could not find whitelist file at ${whitelist_file}" + exit 167 + fi + + while IFS= read -r dir || [ -n "$dir" ]; do + [ -z "$dir" ] && continue path=${PCL_DIR}/${dir} - find ${path} -type f -iname *.[ch] -o -iname *.[ch]pp -o -iname *.[ch]xx \ - -iname *.cu | xargs -n1 ${formatter} -i -style=file - done + find ${path} -type f \( -iname "*.[ch]" -o -iname "*.[ch]pp" -o -iname "*.[ch]xx" -o -iname "*.cu" \) | xargs -n1 ${formatter} -i -style=file + done < "${whitelist_file}" } -format $@ +format "$@" diff --git a/.dev/whitelist.txt b/.dev/whitelist.txt new file mode 100644 index 00000000..52ba06c8 --- /dev/null +++ b/.dev/whitelist.txt @@ -0,0 +1,33 @@ +apps/cloud_composer/include/pcl/apps/cloud_composer +apps/cloud_composer/src/point_selectors +apps/cloud_composer/src/tool_interface +apps/cloud_composer/tools +apps/cloud_composer/src/cloud_composer.cpp +apps/cloud_composer/src/cloud_viewer.cpp +apps/cloud_composer/src/commands.cpp +apps/cloud_composer/src/item_inspector.cpp +apps/cloud_composer/src/items/cloud_composer_item.cpp +apps/cloud_composer/src/items/fpfh_item.cpp +apps/cloud_composer/src/main.cpp +apps/cloud_composer/src/merge_selection.cpp +apps/cloud_composer/src/properties_model.cpp +apps/cloud_composer/src/signal_multiplexer.cpp +apps/cloud_composer/src/toolbox_model.cpp +apps/cloud_composer/src/transform_clouds.cpp +apps/cloud_composer/src/work_queue.cpp +apps/3d_rec_framework +apps/in_hand_scanner +apps/include +apps/modeler +apps/src +benchmarks +2d +geometry +ml +octree +simulation +stereo +tracking +registration +gpu/containers +gpu/segmentation diff --git a/CHANGES.md b/CHANGES.md index 76b21eb3..ff281cc6 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,5 +1,98 @@ # ChangeList +## = 1.15.1 (26 August 2025) = + +### Notable changes + +**New features** *added to PCL* + +* **[search]** Add support for nanoflann (faster alternative to pcl::search::KdTree) [[#6250](https://github.com/PointCloudLibrary/pcl/pull/6250)] + +### Changes grouped by module + +#### CMake: + +* Fix get the root directory path of Boost [[#6259](https://github.com/PointCloudLibrary/pcl/pull/6259)] +* Detect alignment when pcl_find_sse is not called & fix detection of Eigen [[#6261](https://github.com/PointCloudLibrary/pcl/pull/6261)] +* Improve SSE/AVX detection on arm and when cross-compiling [[#6264](https://github.com/PointCloudLibrary/pcl/pull/6264)] +* Fix CMake warning related to FLANN_ROOT [[#6266](https://github.com/PointCloudLibrary/pcl/pull/6266)] + +#### libpcl_common: + +* Make copyPoint work with point types having a field of the same name … [[#6300](https://github.com/PointCloudLibrary/pcl/pull/6300)] +* Add potentially missing include cassert [[#6308](https://github.com/PointCloudLibrary/pcl/pull/6308)] + +#### libpcl_cuda: + +* Support CUDA 13 [[#6316](https://github.com/PointCloudLibrary/pcl/pull/6316)] + +#### libpcl_filters: + +* Make FarthestPointFilter respect user supplied indices [[#6286](https://github.com/PointCloudLibrary/pcl/pull/6286)] +* Re-add instantiation of Convolution for MSVC [[#6310](https://github.com/PointCloudLibrary/pcl/pull/6310)] + +#### libpcl_gpu: + +* Fix CUDA 12.9 transform_reduce ambiguity [[#6299](https://github.com/PointCloudLibrary/pcl/pull/6299)] +* Support CUDA 13 [[#6316](https://github.com/PointCloudLibrary/pcl/pull/6316)] + +#### libpcl_io: + +* Fix writing pcl::PointCloud to IFS file [[#6262](https://github.com/PointCloudLibrary/pcl/pull/6262)] +* Increase accuracy of OctreePointCloudCompression [[#6273](https://github.com/PointCloudLibrary/pcl/pull/6273)] + +#### libpcl_ml: + +* Fix deprecated vsprintf warning in SVM implementation [[#6312](https://github.com/PointCloudLibrary/pcl/pull/6312)] + +#### libpcl_octree: + +* Increase accuracy of OctreePointCloudCompression [[#6273](https://github.com/PointCloudLibrary/pcl/pull/6273)] +* Optimization for Octree radiusSearch [[#6313](https://github.com/PointCloudLibrary/pcl/pull/6313)] + +#### libpcl_outofcore: + +* Make the dependency of "outofcore" on "visualization" optional. [[#6254](https://github.com/PointCloudLibrary/pcl/pull/6254)] + +#### libpcl_registration: + +* add explicit instantiations to transformation estimation LM and one to ICP [[#6258](https://github.com/PointCloudLibrary/pcl/pull/6258)] +* Make GICP use CorrespondenceEstimation [[#6278](https://github.com/PointCloudLibrary/pcl/pull/6278)] + +#### libpcl_sample_consensus: + +* SAC: add getInliers, getModel, getModelCoefficients to avoid copying data [[#6304](https://github.com/PointCloudLibrary/pcl/pull/6304)] + +#### libpcl_search: + +* **[new feature]** Add support for nanoflann (faster alternative to pcl::search::KdTree) [[#6250](https://github.com/PointCloudLibrary/pcl/pull/6250)] +* Add option to manually set projection matrix in OrganizedNeighbor [[#6268](https://github.com/PointCloudLibrary/pcl/pull/6268)] + +#### libpcl_simulation: + +* Simulation: replace gluErrorString with switch-case [[#6253](https://github.com/PointCloudLibrary/pcl/pull/6253)] + +#### libpcl_surface: + +* Fix: Potential Vulnerability in Cloned zlib-Function [[#6245](https://github.com/PointCloudLibrary/pcl/pull/6245)] +* Fix: Potential Vulnerability in Cloned zlib-Function [[#6246](https://github.com/PointCloudLibrary/pcl/pull/6246)] +* Fix potential vulnerable cloned zlib-functions [[#6275](https://github.com/PointCloudLibrary/pcl/pull/6275)] +* Fix potential vulnerable cloned zlib-functions [[#6274](https://github.com/PointCloudLibrary/pcl/pull/6274)] + +#### PCL Docs: + +* Modernize cmake config template [[#6235](https://github.com/PointCloudLibrary/pcl/pull/6235)] + +#### PCL Tutorials: + +* Update CMake commands in tutorials [[#6282](https://github.com/PointCloudLibrary/pcl/pull/6282)] + +#### CI: + +* Update/improve CI [[#6242](https://github.com/PointCloudLibrary/pcl/pull/6242)] +* switch to VS 2022 on x64 Windows [[#6247](https://github.com/PointCloudLibrary/pcl/pull/6247)] +* Add and use python for formatting. [[#6298](https://github.com/PointCloudLibrary/pcl/pull/6298)] + ## = 1.15.0 (22 February 2025) = ### Notable changes diff --git a/CMakeLists.txt b/CMakeLists.txt index 617498c7..4571a0e4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -27,7 +27,7 @@ if("${CMAKE_BUILD_TYPE}" STREQUAL "") set(CMAKE_BUILD_TYPE RelWithDebInfo CACHE STRING "build type default to RelWithDebInfo, set to Release to improve performance" FORCE) endif() -project(PCL VERSION 1.15.0) +project(PCL VERSION 1.15.1) string(TOLOWER ${PROJECT_NAME} PROJECT_NAME_LOWER) if(MSVC AND ("${MSVC_VERSION}" LESS 1910)) @@ -65,6 +65,9 @@ elseif(MINGW) set(CMAKE_COMPILER_IS_MINGW 1) endif() +# Ensure try_compile sets the include paths (e.g. for Eigen3) +set(CMAKE_TRY_COMPILE_CONFIGURATION ${CMAKE_BUILD_TYPE}) + # https://github.com/fish-shell/fish-shell/issues/5865 include(CheckCXXSourceCompiles) CHECK_CXX_SOURCE_COMPILES(" @@ -104,6 +107,10 @@ if(CMAKE_TIMING_VERBOSE AND UNIX) set_property(GLOBAL PROPERTY RULE_LAUNCH_COMPILE "${CMAKE_SOURCE_DIR}/cmake/custom_output.sh") endif() +# check for allocation functions that return aligned memory +include("${PCL_SOURCE_DIR}/cmake/pcl_alignment.cmake") +PCL_CHECK_FOR_ALIGNMENT() + # check for SSE flags include("${PCL_SOURCE_DIR}/cmake/pcl_find_sse.cmake") if(PCL_ENABLE_SSE AND "${CMAKE_CXX_FLAGS}" STREQUAL "${CMAKE_CXX_FLAGS_DEFAULT}") @@ -228,13 +235,14 @@ endif() if(CMAKE_COMPILER_IS_CLANG) if("${CMAKE_C_FLAGS}" STREQUAL "${CMAKE_CXX_FLAGS_DEFAULT}") - set(CMAKE_C_FLAGS "-Qunused-arguments") + string(APPEND CMAKE_C_FLAGS " -Wall -Wextra") endif() if("${CMAKE_CXX_FLAGS}" STREQUAL "") - set(CMAKE_CXX_FLAGS "-ftemplate-depth=1024 -Qunused-arguments -Wno-invalid-offsetof ${SSE_FLAGS} ${AVX_FLAGS}") # Unfortunately older Clang versions do not have this: -Wno-unnamed-type-template-args + set(CMAKE_CXX_FLAGS "-ftemplate-depth=1024 -Wno-invalid-offsetof ${SSE_FLAGS} ${AVX_FLAGS}") # Unfortunately older Clang versions do not have this: -Wno-unnamed-type-template-args if(APPLE AND WITH_CUDA AND CUDA_FOUND) string(APPEND CMAKE_CXX_FLAGS " -stdlib=libstdc++") endif() + string(APPEND CMAKE_CXX_FLAGS " -Wall -Wextra") endif() set(CLANG_LIBRARIES "stdc++") endif() @@ -353,6 +361,14 @@ else() endif() endif() +find_package(nanoflann 1.4.2 QUIET) +if(TARGET nanoflann::nanoflann) + set(PCL_HAS_NANOFLANN 1) + message(STATUS "Found nanoflann") +else() + message(STATUS "nanoflann was not found, so some PCL classes will not be available.") +endif() + # libusb option(WITH_LIBUSB "Build USB RGBD-Camera drivers" TRUE) if(WITH_LIBUSB) @@ -434,6 +450,8 @@ if(WITH_SYSTEM_ZLIB) if(ZLIB_FOUND) set(HAVE_ZLIB ON) endif() +else() + message(WARNING "CMake will use a ZLIB version bundled with the PCL source code. However, that is an older version which may pose a risk and may be removed in a future PCL release. It is recommended to install an up-to-date version of ZLIB on your system and set WITH_SYSTEM_ZLIB=TRUE.") endif() option(WITH_SYSTEM_CJSON "Use system cJSON" TRUE) @@ -461,6 +479,11 @@ else() endif() unset(CMAKE_REQUIRED_LIBRARIES) +### --[ Set variables for pcl_config.h +if (BUILD_visualization) + set(PCL_VISUALIZATION_AVAILABLE TRUE) +endif() + ### ---[ Create the config.h file set(pcl_config_h_in "${CMAKE_CURRENT_SOURCE_DIR}/pcl_config.h.in") set(pcl_config_h "${CMAKE_CURRENT_BINARY_DIR}/include/pcl/pcl_config.h") @@ -468,6 +491,7 @@ configure_file("${pcl_config_h_in}" "${pcl_config_h}") PCL_ADD_INCLUDES(common "" "${pcl_config_h}") include_directories("${CMAKE_CURRENT_BINARY_DIR}/include") +## ---[ PCL modules collect_subproject_directory_names("${PCL_SOURCE_DIR}" "CMakeLists.txt" PCL_MODULES_NAMES PCL_MODULES_DIRS doc) set(PCL_MODULES_NAMES_UNSORTED ${PCL_MODULES_NAMES}) topological_sort(PCL_MODULES_NAMES PCL_ _DEPENDS) diff --git a/PCLConfig.cmake.in b/PCLConfig.cmake.in index 6e1af47c..d90f4a22 100644 --- a/PCLConfig.cmake.in +++ b/PCLConfig.cmake.in @@ -1,10 +1,23 @@ # ------------------------------------------------------------------------------------ # Helper to use PCL from outside project # -# target_link_libraries(my_fabulous_target PCL_XXX_LIBRARIES) where XXX is the -# upper cased xxx from : +# Search for PCL: +# Request all PCL modules: +# find_package(PCL CONFIG REQUIRED) +# Or request only specific PCL modules: +# find_package(PCL CONFIG REQUIRED COMPONENTS xxx yyy) +# +# Link to PCL: +# Link to all found PCL modules: +# target_link_libraries(my_fabulous_target ${PCL_LIBRARIES}) +# Or link only to specific modules: +# target_link_libraries(my_fabulous_target pcl_xxx pcl_yyy) +# +# Where xxx and yyy are module names from the following list: # @PCLCONFIG_AVAILABLE_COMPONENTS_LIST@ # +# Some additional variables are set by PCLConfig.cmake, which are not needed when +# using the (modern) linking approach described above: # PCL_INCLUDE_DIRS is filled with PCL and available 3rdparty headers # PCL_LIBRARY_DIRS is filled with PCL components libraries install directory and # 3rdparty libraries paths @@ -12,9 +25,14 @@ # www.pointclouds.org #------------------------------------------------------------------------------------ + # Set default policy behavior similar to minimum requirement version cmake_policy(VERSION 3.16.3) +if(POLICY CMP0144) + cmake_policy(SET CMP0144 NEW) +endif() + list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/Modules") ### ---[ some useful macros diff --git a/README.md b/README.md index 87a931f2..61f62529 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ [![Release][release-image]][releases] [![License][license-image]][license] -[release-image]: https://img.shields.io/badge/release-1.15.0-green.svg?style=flat +[release-image]: https://img.shields.io/badge/release-1.15.1-green.svg?style=flat [releases]: https://github.com/PointCloudLibrary/pcl/releases [license-image]: https://img.shields.io/badge/license-BSD-green.svg?style=flat @@ -25,7 +25,7 @@ Continuous integration [ci-ubuntu-22.04]: https://dev.azure.com/PointCloudLibrary/pcl/_apis/build/status/9?branchName=master&stageName=Build%20Clang&jobName=Ubuntu&configuration=Ubuntu%2022.04%20Clang&label=Ubuntu%2022.04%20Clang [ci-ubuntu-24.04]: https://dev.azure.com/PointCloudLibrary/pcl/_apis/build/status/9?branchName=master&stageName=Build%20GCC&jobName=Ubuntu&configuration=Ubuntu%2024.04%20GCC&label=Ubuntu%2024.04%20GCC [ci-windows-x86]: https://dev.azure.com/PointCloudLibrary/pcl/_apis/build/status/9?branchName=master&stageName=Build%20MSVC&jobName=Windows%20Build&configuration=Windows%20Build%20x86&label=Windows%20VS2019%20x86 -[ci-windows-x64]: https://dev.azure.com/PointCloudLibrary/pcl/_apis/build/status/9?branchName=master&stageName=Build%20MSVC&jobName=Windows%20Build&configuration=Windows%20Build%20x64&label=Windows%20VS2019%20x64 +[ci-windows-x64]: https://dev.azure.com/PointCloudLibrary/pcl/_apis/build/status/9?branchName=master&stageName=Build%20MSVC&jobName=Windows%20Build&configuration=Windows%20Build%20x64&label=Windows%20VS2022%20x64 [ci-macos-13]: https://dev.azure.com/PointCloudLibrary/pcl/_apis/build/status/9?branchName=master&stageName=Build%20Clang&jobName=macOS&configuration=macOS%20Ventura%2013&label=macOS%20Ventura%2013 [ci-macos-14]: https://dev.azure.com/PointCloudLibrary/pcl/_apis/build/status/9?branchName=master&stageName=Build%20Clang&jobName=macOS&configuration=macOS%20Sonoma%2014&label=macOS%20Sonoma%2014 [ci-docs]: https://dev.azure.com/PointCloudLibrary/pcl/_apis/build/status/Documentation?branchName=master diff --git a/apps/cloud_composer/include/pcl/apps/cloud_composer/cloud_browser.h b/apps/cloud_composer/include/pcl/apps/cloud_composer/cloud_browser.h index c5e8c7d6..973ca001 100644 --- a/apps/cloud_composer/include/pcl/apps/cloud_composer/cloud_browser.h +++ b/apps/cloud_composer/include/pcl/apps/cloud_composer/cloud_browser.h @@ -42,40 +42,35 @@ class QItemSelectionModel; -namespace pcl -{ - namespace cloud_composer - { - /** \brief View class for displaying project composition - * \author Jeremie Papon - * \ingroup cloud_composer - */ - class ProjectModel; - class CloudBrowser : public QTreeView - { - Q_OBJECT - public: - CloudBrowser (QWidget* parent = nullptr); - - void - setModel (QAbstractItemModel* new_model) override; - - private: - ProjectModel* current_project_model_; - - }; - - class BackgroundDelegate : public QStyledItemDelegate - { - public: - explicit - BackgroundDelegate (QObject *parent = nullptr) - : QStyledItemDelegate(parent) {} - - void - paint (QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const override; - - }; - - } -} +namespace pcl { +namespace cloud_composer { +/** \brief View class for displaying project composition + * \author Jeremie Papon + * \ingroup cloud_composer + */ +class ProjectModel; +class CloudBrowser : public QTreeView { + Q_OBJECT +public: + CloudBrowser(QWidget* parent = nullptr); + + void + setModel(QAbstractItemModel* new_model) override; + +private: + ProjectModel* current_project_model_; +}; + +class BackgroundDelegate : public QStyledItemDelegate { +public: + explicit BackgroundDelegate(QObject* parent = nullptr) : QStyledItemDelegate(parent) + {} + + void + paint(QPainter* painter, + const QStyleOptionViewItem& option, + const QModelIndex& index) const override; +}; + +} // namespace cloud_composer +} // namespace pcl diff --git a/apps/cloud_composer/include/pcl/apps/cloud_composer/cloud_composer.h b/apps/cloud_composer/include/pcl/apps/cloud_composer/cloud_composer.h index 9fbfdcc5..1da2fb71 100644 --- a/apps/cloud_composer/include/pcl/apps/cloud_composer/cloud_composer.h +++ b/apps/cloud_composer/include/pcl/apps/cloud_composer/cloud_composer.h @@ -37,7 +37,7 @@ #pragma once -//PCL +// PCL #include #include @@ -45,125 +45,122 @@ class QTreeView; -namespace pcl -{ - namespace cloud_composer - { - class ProjectModel; - class CloudViewer; - class CloudCommand; - class ToolFactory; - class ToolBoxModel; - class SignalMultiplexer; - - /** \brief MainWindow of cloud_composer application - * \author Jeremie Papon - * \ingroup cloud_composer - * The following member objects are defined in the ui file and can be manipulated: - * * cloud_viewer_ is the view which contains the PCLVisualizer & QVTKWidget - * * cloud_browser_ is the tree view in the left dock - * * item_inspector_ is the details view in the left dock - * * tool_box_view_ is the tool box in right dock - * * tool_parameter_view_ shows adjustable parameters for currently selected tool - * * undo_view_ is the undo stack view in the right dock - */ - class ComposerMainWindow : public QMainWindow, private Ui::ComposerMainWindow - { - Q_OBJECT - public: - explicit ComposerMainWindow (QWidget *parent = nullptr); - ~ComposerMainWindow (); - - Q_SIGNALS: - /** \brief Signal emitted when the active project is switched - ie a different project tab is selected */ - void - activeProjectChanged (ProjectModel* new_model, ProjectModel* previous_model); - - /** \brief This signal tells the current project to insert a cloud using a file dialog box */ - void - insertNewCloudFromFile (); - - /** \brief This signal tells the current project to insert a cloud from and RGB and Depth image using a file dialog box */ - void - insertNewCloudFromRGBandDepth (); - - /** \brief This signal tells the current project to save currently selected cloud to file */ - void - saveSelectedCloudToFile (); - - public Q_SLOTS: - //Slots for File Menu Actions - void - on_action_new_project__triggered (/*QString name = "unsaved project"*/); - void - on_action_open_cloud_as_new_project__triggered (); - void - on_action_open_project__triggered (); - void - on_action_save_project__triggered (); - void - on_action_save_project_as__triggered (); - void - on_action_save_selected_cloud__triggered (); - void - on_action_exit__triggered (); - - //Slots for Edit Menu Actions - void - on_action_insert_from_file__triggered (); - void - on_action_insert_from_openNi_source__triggered (); - void - on_action_insert_from_rgb_depth__triggered (); - - - - void - setCurrentModel (ProjectModel* model); - - void - setMouseStyleAction (interactor_styles::INTERACTOR_STYLES selected_style); - - void - enqueueToolAction (AbstractTool* tool); - - private: - void - connectFileActions (); - void - connectEditActions (); - - void - connectViewActions (); - - void - initializeCloudBrowser (); - void - initializeCloudViewer (); - void - initializeItemInspector (); - - void - initializeToolBox (); - void - initializePlugins (); - - - /** \brief Pointer to the model which is currently being viewed */ - ProjectModel* current_model_; - QItemSelectionModel* current_selection_model_; - - QMap name_model_map_; - - QUndoGroup *undo_group_; - - QItemSelectionModel* tool_selection_model_; - ToolBoxModel* tool_box_model_; - - SignalMultiplexer* multiplexer_; - - QActionGroup* mouse_style_group_; - }; - - } -} +namespace pcl { +namespace cloud_composer { +class ProjectModel; +class CloudViewer; +class CloudCommand; +class ToolFactory; +class ToolBoxModel; +class SignalMultiplexer; + +/** \brief MainWindow of cloud_composer application + * \author Jeremie Papon + * \ingroup cloud_composer + * The following member objects are defined in the ui file and can be manipulated: + * * cloud_viewer_ is the view which contains the PCLVisualizer & QVTKWidget + * * cloud_browser_ is the tree view in the left dock + * * item_inspector_ is the details view in the left dock + * * tool_box_view_ is the tool box in right dock + * * tool_parameter_view_ shows adjustable parameters for currently selected tool + * * undo_view_ is the undo stack view in the right dock + */ +class ComposerMainWindow : public QMainWindow, private Ui::ComposerMainWindow { + Q_OBJECT +public: + explicit ComposerMainWindow(QWidget* parent = nullptr); + ~ComposerMainWindow(); + +Q_SIGNALS: + /** \brief Signal emitted when the active project is switched - ie a different project + * tab is selected */ + void + activeProjectChanged(ProjectModel* new_model, ProjectModel* previous_model); + + /** \brief This signal tells the current project to insert a cloud using a file dialog + * box */ + void + insertNewCloudFromFile(); + + /** \brief This signal tells the current project to insert a cloud from and RGB and + * Depth image using a file dialog box */ + void + insertNewCloudFromRGBandDepth(); + + /** \brief This signal tells the current project to save currently selected cloud to + * file */ + void + saveSelectedCloudToFile(); + +public Q_SLOTS: + // Slots for File Menu Actions + void on_action_new_project__triggered(/*QString name = "unsaved project"*/); + void + on_action_open_cloud_as_new_project__triggered(); + void + on_action_open_project__triggered(); + void + on_action_save_project__triggered(); + void + on_action_save_project_as__triggered(); + void + on_action_save_selected_cloud__triggered(); + void + on_action_exit__triggered(); + + // Slots for Edit Menu Actions + void + on_action_insert_from_file__triggered(); + void + on_action_insert_from_openNi_source__triggered(); + void + on_action_insert_from_rgb_depth__triggered(); + + void + setCurrentModel(ProjectModel* model); + + void + setMouseStyleAction(interactor_styles::INTERACTOR_STYLES selected_style); + + void + enqueueToolAction(AbstractTool* tool); + +private: + void + connectFileActions(); + void + connectEditActions(); + + void + connectViewActions(); + + void + initializeCloudBrowser(); + void + initializeCloudViewer(); + void + initializeItemInspector(); + + void + initializeToolBox(); + void + initializePlugins(); + + /** \brief Pointer to the model which is currently being viewed */ + ProjectModel* current_model_; + QItemSelectionModel* current_selection_model_; + + QMap name_model_map_; + + QUndoGroup* undo_group_; + + QItemSelectionModel* tool_selection_model_; + ToolBoxModel* tool_box_model_; + + SignalMultiplexer* multiplexer_; + + QActionGroup* mouse_style_group_; +}; + +} // namespace cloud_composer +} // namespace pcl diff --git a/apps/cloud_composer/include/pcl/apps/cloud_composer/cloud_view.h b/apps/cloud_composer/include/pcl/apps/cloud_composer/cloud_view.h index 27780fa5..09723d2b 100644 --- a/apps/cloud_composer/include/pcl/apps/cloud_composer/cloud_view.h +++ b/apps/cloud_composer/include/pcl/apps/cloud_composer/cloud_view.h @@ -37,130 +37,138 @@ #pragma once -#include - -#include - +#include #include #include -#include +#include -#include -#include #include +#include +#include +#include #include class QItemSelection; class QStandardItem; -namespace pcl -{ - namespace cloud_composer +namespace pcl { +namespace cloud_composer { +class ProjectModel; +/** \brief View class for displaying ProjectModel data using PCLVisualizer + * \author Jeremie Papon + * \ingroup cloud_composer + */ +class CloudView : public QWidget { + Q_OBJECT + +public: + CloudView(QWidget* parent = nullptr); + CloudView(const CloudView& to_copy); + CloudView(ProjectModel* model, QWidget* parent = nullptr); + + void + setModel(ProjectModel* new_model); + + ProjectModel* + getModel() const + { + return model_; + } + + PCLQVTKWidget* + getQVTK() const + { + return qvtk_; + } + + pcl::visualization::PCLVisualizer::Ptr + getPCLVisualizer() const { - class ProjectModel; - /** \brief View class for displaying ProjectModel data using PCLVisualizer - * \author Jeremie Papon - * \ingroup cloud_composer - */ - class CloudView : public QWidget - { - Q_OBJECT - - public: - CloudView (QWidget* parent = nullptr); - CloudView (const CloudView& to_copy); - CloudView (ProjectModel* model, QWidget* parent = nullptr); - - void - setModel (ProjectModel* new_model); - - ProjectModel* - getModel () const { return model_; } - - PCLQVTKWidget* - getQVTK() const { return qvtk_; } - - pcl::visualization::PCLVisualizer::Ptr - getPCLVisualizer () const { return vis_; } - - void - setAxisVisibility (bool visible); - - void - setInteractorStyle (interactor_styles::INTERACTOR_STYLES style); - public Q_SLOTS: - void - refresh (); - - /** \brief Slot called when the item selected in cloud browser changes */ - void - selectedItemChanged (const QItemSelection & selected, const QItemSelection & deselected); - - /** \brief Slot called when the data in model changes */ - void - dataChanged ( const QModelIndex & topLeft, const QModelIndex & bottomRight ); - - protected Q_SLOTS: - /** \brief Slot called when an item in the model changes - * \param topLeft - * \param bottomRight - */ - void - itemChanged (QStandardItem* item); - - /** \brief Slot called when rows inserted to model - * \param start Start of new rows (inclusive) - * \param end End of new rows (inclusive) - */ - void - rowsInserted (const QModelIndex& parent, int start, int end); - - void - rowsAboutToBeRemoved (const QModelIndex& parent, int start, int end); - - void - selectionCompleted (vtkObject* caller, unsigned long event_id, void* client_data, void* call_data); - - void - manipulationCompleted (vtkObject* caller, unsigned long event_id, void* client_data, void* call_data); - - protected: - void - paintEvent (QPaintEvent* event) override; - void - resizeEvent (QResizeEvent* event) override; - // void scrollContentsBy (int dx, int dy); - - - - private: - void - connectSignalsAndSlots (); - - /** \brief Internal function for setting up the style_switch_ */ - void - initializeInteractorSwitch (); - - void - addOrientationMarkerWidgetAxes (); - void - removeOrientationMarkerWidgetAxes (); - - pcl::visualization::PCLVisualizer::Ptr vis_; - ProjectModel* model_; - - PCLQVTKWidget* qvtk_; - - vtkSmartPointer style_switch_; - - vtkSmartPointer axes_widget_; - vtkSmartPointer axes_; - - /** \brief Manages VTK events by connecting them to QT slots */ - vtkSmartPointer connections_; - }; + return vis_; } -} -Q_DECLARE_METATYPE (pcl::cloud_composer::CloudView); + void + setAxisVisibility(bool visible); + + void + setInteractorStyle(interactor_styles::INTERACTOR_STYLES style); +public Q_SLOTS: + void + refresh(); + + /** \brief Slot called when the item selected in cloud browser changes */ + void + selectedItemChanged(const QItemSelection& selected, const QItemSelection& deselected); + + /** \brief Slot called when the data in model changes */ + void + dataChanged(const QModelIndex& topLeft, const QModelIndex& bottomRight); + +protected Q_SLOTS: + /** \brief Slot called when an item in the model changes + * \param topLeft + * \param bottomRight + */ + void + itemChanged(QStandardItem* item); + + /** \brief Slot called when rows inserted to model + * \param start Start of new rows (inclusive) + * \param end End of new rows (inclusive) + */ + void + rowsInserted(const QModelIndex& parent, int start, int end); + + void + rowsAboutToBeRemoved(const QModelIndex& parent, int start, int end); + + void + selectionCompleted(vtkObject* caller, + unsigned long event_id, + void* client_data, + void* call_data); + + void + manipulationCompleted(vtkObject* caller, + unsigned long event_id, + void* client_data, + void* call_data); + +protected: + void + paintEvent(QPaintEvent* event) override; + void + resizeEvent(QResizeEvent* event) override; + // void scrollContentsBy (int dx, int dy); + +private: + void + connectSignalsAndSlots(); + + /** \brief Internal function for setting up the style_switch_ */ + void + initializeInteractorSwitch(); + + void + addOrientationMarkerWidgetAxes(); + void + removeOrientationMarkerWidgetAxes(); + + pcl::visualization::PCLVisualizer::Ptr vis_; + ProjectModel* model_; + + PCLQVTKWidget* qvtk_; + + vtkSmartPointer style_switch_; + + vtkSmartPointer axes_widget_; + vtkSmartPointer axes_; + + /** \brief Manages VTK events by connecting them to QT slots */ + vtkSmartPointer connections_; +}; +} // namespace cloud_composer +} // namespace pcl + +Q_DECLARE_METATYPE(pcl::cloud_composer::CloudView); diff --git a/apps/cloud_composer/include/pcl/apps/cloud_composer/cloud_viewer.h b/apps/cloud_composer/include/pcl/apps/cloud_composer/cloud_viewer.h index df10dc1f..3e6489fc 100644 --- a/apps/cloud_composer/include/pcl/apps/cloud_composer/cloud_viewer.h +++ b/apps/cloud_composer/include/pcl/apps/cloud_composer/cloud_viewer.h @@ -37,48 +37,44 @@ #pragma once +#include +#include +#include + #include -#include -#include -#include +namespace pcl { +namespace cloud_composer { + +/** \brief Tabbed widget for containing CloudView widgets + * \author Jeremie Papon + * \ingroup cloud_composer + */ +class CloudViewer : public QTabWidget { + Q_OBJECT + +public: + CloudViewer(QWidget* parent = nullptr); + ProjectModel* + getModel() const; + +public Q_SLOTS: + void + addModel(ProjectModel* new_model); -namespace pcl -{ - namespace cloud_composer - { - - /** \brief Tabbed widget for containing CloudView widgets - * \author Jeremie Papon - * \ingroup cloud_composer - */ - class CloudViewer : public QTabWidget - { - Q_OBJECT + void + modelChanged(int index); - public: - - CloudViewer (QWidget* parent = nullptr); - ProjectModel* getModel () const; + void + addNewProject(ProjectModel* new_model); - public Q_SLOTS: - void - addModel (ProjectModel* new_model); - - void - modelChanged (int index); - - void - addNewProject (ProjectModel* new_model); - - Q_SIGNALS: - void - newModelSelected (ProjectModel *new_model); +Q_SIGNALS: + void + newModelSelected(ProjectModel* new_model); - private: - - pcl::visualization::PCLVisualizer::Ptr vis_; - QMap model_view_map_; - }; - } -} +private: + pcl::visualization::PCLVisualizer::Ptr vis_; + QMap model_view_map_; +}; +} // namespace cloud_composer +} // namespace pcl diff --git a/apps/cloud_composer/include/pcl/apps/cloud_composer/commands.h b/apps/cloud_composer/include/pcl/apps/cloud_composer/commands.h index 5186af6a..e47c399b 100644 --- a/apps/cloud_composer/include/pcl/apps/cloud_composer/commands.h +++ b/apps/cloud_composer/include/pcl/apps/cloud_composer/commands.h @@ -41,180 +41,171 @@ #include -namespace pcl -{ - namespace cloud_composer +namespace pcl { +namespace cloud_composer { +class AbstractTool; +class ProjectModel; +struct OutputPair { + QList input_items_; + QList output_items_; +}; + +class CloudCommand : public QUndoCommand { +public: + CloudCommand(ConstItemList input_data, QUndoCommand* parent = nullptr); + + ~CloudCommand(); + + virtual bool + runCommand(AbstractTool* tool) = 0; + + void + undo() override = 0; + + void + redo() override = 0; + + // QList + // executeToolOnTemplateCloud (AbstractTool* tool, ConstItemList &input_data); + + void + setProjectModel(ProjectModel* model); + + inline void + setInputData(ConstItemList input_data) + { + original_data_ = std::move(input_data); + } + +protected: + /** \brief Removes the original item(s) from the model and replaces with the + * replacement(s) Replacements are only inserted once, original items must have same + * parent This stores the removed items in removed_items_ + */ + bool + replaceOriginalWithNew(const QList& originals, + const QList& new_items); + + /** \brief This removes new_items from the model and restores originals */ + bool + restoreOriginalRemoveNew(const QList& originals, + const QList& new_items); + + ConstItemList original_data_; + + QMap removed_to_parent_map_; + QList output_data_; + ProjectModel* project_model_; + + /** \brief This determines if we delete original items or not on destruction + * If the command is being deleted because stack is at limit, then we want + * to only delete the originals, since the command is staying for good (new items + * shouldn't be deleted) On the other hand, if we destruct after an undo, then we want + * to delete the new items (but not the originals) + */ + bool last_was_undo_; + + /** \brief This is used to check if a templated version of a tool can be used + * For this to return true, all items must be clouds, and must have the same template + * type + */ + bool + canUseTemplates(ConstItemList& input_data); + + bool can_use_templates_; + int template_type_; +}; + +class ModifyItemCommand : public CloudCommand { +public: + ModifyItemCommand(ConstItemList input_data, QUndoCommand* parent = nullptr); + + bool + runCommand(AbstractTool* tool) override; + + void + undo() override; + + void + redo() override; + +private: +}; + +class NewItemCloudCommand : public CloudCommand { +public: + NewItemCloudCommand(ConstItemList input_data, QUndoCommand* parent = nullptr); + + bool + runCommand(AbstractTool* tool) override; + + void + undo() override; + + void + redo() override; +}; + +class SplitCloudCommand : public CloudCommand { +public: + SplitCloudCommand(ConstItemList input_data, QUndoCommand* parent = nullptr); + + bool + runCommand(AbstractTool* tool) override; + + void + undo() override; + + void + redo() override; + +private: +}; + +class DeleteItemCommand : public CloudCommand { +public: + DeleteItemCommand(ConstItemList input_data, QUndoCommand* parent = nullptr); + + bool + runCommand(AbstractTool* tool) override; + + void + undo() override; + + void + redo() override; + +private: +}; + +class MergeCloudCommand : public CloudCommand { +public: + /** \brief Construct for a merge command + * \param[in] input_data Input list of CloudItem s from the project model which will + * be merged \param[in] temporary_clouds Input list of CloudItems which + */ + MergeCloudCommand(ConstItemList input_data, QUndoCommand* parent = nullptr); + + bool + runCommand(AbstractTool* tool) override; + + void + undo() override; + + void + redo() override; + + inline void + setSelectedIndicesMap( + const QMap& selected_item_index_map) { - class AbstractTool; - class ProjectModel; - struct OutputPair - { - QList input_items_; - QList output_items_; - }; - - - - class CloudCommand : public QUndoCommand - { - public: - CloudCommand (ConstItemList input_data, QUndoCommand* parent = nullptr); - - - ~CloudCommand (); - - virtual bool - runCommand (AbstractTool* tool) = 0; - - void - undo () override = 0; - - void - redo () override = 0; - - //QList - // executeToolOnTemplateCloud (AbstractTool* tool, ConstItemList &input_data); - - void - setProjectModel (ProjectModel* model); - - inline void - setInputData (ConstItemList input_data) - { - original_data_ = std::move(input_data); - } - protected: - /** \brief Removes the original item(s) from the model and replaces with the replacement(s) - * Replacements are only inserted once, original items must have same parent - * This stores the removed items in removed_items_ - */ - bool - replaceOriginalWithNew (const QList & originals, const QList & new_items); - - /** \brief This removes new_items from the model and restores originals */ - bool - restoreOriginalRemoveNew (const QList & originals, const QList & new_items); - - ConstItemList original_data_; - - QMap removed_to_parent_map_; - QList output_data_; - ProjectModel* project_model_; - - /** \brief This determines if we delete original items or not on destruction - * If the command is being deleted because stack is at limit, then we want - * to only delete the originals, since the command is staying for good (new items shouldn't be deleted) - * On the other hand, if we destruct after an undo, then we want to delete the new items (but not the originals) - */ - bool last_was_undo_; - - /** \brief This is used to check if a templated version of a tool can be used - * For this to return true, all items must be clouds, and must have the same template type - */ - bool - canUseTemplates (ConstItemList &input_data); - - bool can_use_templates_; - int template_type_; - }; - - class ModifyItemCommand : public CloudCommand - { - public: - ModifyItemCommand (ConstItemList input_data, QUndoCommand* parent = nullptr); - - bool - runCommand (AbstractTool* tool) override; - - void - undo () override; - - void - redo () override; - private: - - - - }; - - class NewItemCloudCommand : public CloudCommand - { - public: - NewItemCloudCommand (ConstItemList input_data, QUndoCommand* parent = nullptr); - - bool - runCommand (AbstractTool* tool) override; - - void - undo () override; - - void - redo () override; - - }; - - - class SplitCloudCommand : public CloudCommand - { - public: - SplitCloudCommand (ConstItemList input_data, QUndoCommand* parent = nullptr); - - bool - runCommand (AbstractTool* tool) override; - - void - undo () override; - - void - redo () override; - private: - - }; - - class DeleteItemCommand : public CloudCommand - { - public: - DeleteItemCommand (ConstItemList input_data, QUndoCommand* parent = nullptr); - - bool - runCommand (AbstractTool* tool) override; - - void - undo () override; - - void - redo () override; - private: - }; - - class MergeCloudCommand : public CloudCommand - { - public: - /** \brief Construct for a merge command - * \param[in] input_data Input list of CloudItem s from the project model which will be merged - * \param[in] temporary_clouds Input list of CloudItems which - */ - MergeCloudCommand (ConstItemList input_data, QUndoCommand* parent = nullptr); - - bool - runCommand (AbstractTool* tool) override; - - void - undo () override; - - void - redo () override; - - inline void - setSelectedIndicesMap( const QMap & selected_item_index_map) - { - selected_item_index_map_ = selected_item_index_map; - } - - private: - QMap selected_item_index_map_; - }; + selected_item_index_map_ = selected_item_index_map; } -} -Q_DECLARE_METATYPE (ConstItemList); +private: + QMap selected_item_index_map_; +}; +} // namespace cloud_composer +} // namespace pcl + +Q_DECLARE_METATYPE(ConstItemList); diff --git a/apps/cloud_composer/include/pcl/apps/cloud_composer/impl/cloud_item.hpp b/apps/cloud_composer/include/pcl/apps/cloud_composer/impl/cloud_item.hpp index 6689967c..6c78b82d 100644 --- a/apps/cloud_composer/include/pcl/apps/cloud_composer/impl/cloud_item.hpp +++ b/apps/cloud_composer/include/pcl/apps/cloud_composer/impl/cloud_item.hpp @@ -1,4 +1,4 @@ - /* +/* * Software License Agreement (BSD License) * * Point Cloud Library (PCL) - www.pointclouds.org @@ -39,45 +39,48 @@ #define IMPL_CLOUD_ITEM_H_ #include -#include // for pcl::make_shared -#include #include +#include // for pcl::make_shared +#include -template void -pcl::cloud_composer::CloudItem::printNumPoints () const +template +void +pcl::cloud_composer::CloudItem::printNumPoints() const { - QVariant variant = this->data (ItemDataRole::CLOUD_TEMPLATED); + QVariant variant = this->data(ItemDataRole::CLOUD_TEMPLATED); typename PointCloud::Ptr cloud; - if ( variant.canConvert ::Ptr> () ) - { - cloud = variant.value ::Ptr> (); + if (variant.canConvert::Ptr>()) { + cloud = variant.value::Ptr>(); } - else - { - qWarning () << "Attempted to cast to template type which does not exist in this item!"; + else { + qWarning() + << "Attempted to cast to template type which does not exist in this item!"; return; } - qDebug () << "CLOUD HAS WIDTH = "<< cloud->width; - + qDebug() << "CLOUD HAS WIDTH = " << cloud->width; } - - -template pcl::cloud_composer::CloudItem* -pcl::cloud_composer::CloudItem::createCloudItemFromTemplate (const QString& name, typename PointCloud::Ptr cloud_ptr) +template +pcl::cloud_composer::CloudItem* +pcl::cloud_composer::CloudItem::createCloudItemFromTemplate( + const QString& name, typename PointCloud::Ptr cloud_ptr) { - pcl::PCLPointCloud2::Ptr cloud_blob = pcl::make_shared (); - toPCLPointCloud2 (*cloud_ptr, *cloud_blob); - CloudItem* cloud_item = new CloudItem ( name, cloud_blob, Eigen::Vector4f (), Eigen::Quaternionf (), false); - cloud_item->setData (QVariant::fromValue(cloud_ptr), ItemDataRole::CLOUD_TEMPLATED); - cloud_item->setPointType (); + pcl::PCLPointCloud2::Ptr cloud_blob = pcl::make_shared(); + toPCLPointCloud2(*cloud_ptr, *cloud_blob); + CloudItem* cloud_item = + new CloudItem(name, cloud_blob, Eigen::Vector4f(), Eigen::Quaternionf(), false); + cloud_item->setData(QVariant::fromValue(cloud_ptr), ItemDataRole::CLOUD_TEMPLATED); + cloud_item->setPointType(); return cloud_item; } +#define PCL_INSTANTIATE_createCloudItemFromTemplate(T) \ + template pcl::cloud_composer::CloudItem* \ + pcl::cloud_composer::CloudItem::createCloudItemFromTemplate( \ + const QString, typename PointCloud::Ptr); -#define PCL_INSTANTIATE_createCloudItemFromTemplate(T) template pcl::cloud_composer::CloudItem* pcl::cloud_composer::CloudItem::createCloudItemFromTemplate(const QString, typename PointCloud::Ptr); - -#define PCL_INSTANTIATE_printNumPoints(T) template void pcl::cloud_composer::CloudItem::getNumPoints(); +#define PCL_INSTANTIATE_printNumPoints(T) \ + template void pcl::cloud_composer::CloudItem::getNumPoints(); #endif diff --git a/apps/cloud_composer/include/pcl/apps/cloud_composer/impl/merge_selection.hpp b/apps/cloud_composer/include/pcl/apps/cloud_composer/impl/merge_selection.hpp index 9574b738..bb913d25 100644 --- a/apps/cloud_composer/include/pcl/apps/cloud_composer/impl/merge_selection.hpp +++ b/apps/cloud_composer/include/pcl/apps/cloud_composer/impl/merge_selection.hpp @@ -1,4 +1,4 @@ - /* +/* * Software License Agreement (BSD License) * * Point Cloud Library (PCL) - www.pointclouds.org @@ -38,81 +38,85 @@ #ifndef IMPL_MERGE_SELECTION_H_ #define IMPL_MERGE_SELECTION_H_ +#include #include +#include #include -#include -template QList -pcl::cloud_composer::MergeSelection::performTemplatedAction (const QList & input_data) +template +QList +pcl::cloud_composer::MergeSelection::performTemplatedAction( + const QList& input_data) { - QList output; - - foreach (const CloudComposerItem* input_item, input_data) - { - QVariant variant = input_item->data (ItemDataRole::CLOUD_TEMPLATED); - if ( ! variant.canConvert ::Ptr> () ) - { - qWarning () << "Attempted to cast to template type which does not exist in this item! (input list)"; + QList output; + + foreach (const CloudComposerItem* input_item, input_data) { + QVariant variant = input_item->data(ItemDataRole::CLOUD_TEMPLATED); + if (!variant.canConvert::Ptr>()) { + qWarning() << "Attempted to cast to template type which does not exist in this " + "item! (input list)"; return output; } } - foreach (const CloudItem* input_item, selected_item_index_map_.keys ()) - { - QVariant variant = input_item->data (ItemDataRole::CLOUD_TEMPLATED); - if ( ! variant.canConvert ::Ptr> () ) - { - qWarning () << "Attempted to cast to template type which does not exist in this item! (selected list)"; + foreach (const CloudItem* input_item, selected_item_index_map_.keys()) { + QVariant variant = input_item->data(ItemDataRole::CLOUD_TEMPLATED); + if (!variant.canConvert::Ptr>()) { + qWarning() << "Attempted to cast to template type which does not exist in this " + "item! (selected list)"; return output; } - } + } pcl::ExtractIndices filter; - typename PointCloud::Ptr merged_cloud (new PointCloud); + typename PointCloud::Ptr merged_cloud(new PointCloud); + + foreach (const CloudItem* input_cloud_item, selected_item_index_map_.keys()) { + input_cloud_item->printNumPoints(); + // If this cloud hasn't been completely selected + if (!input_data.contains(input_cloud_item)) { + typename PointCloud::Ptr input_cloud = + input_cloud_item->data(ItemDataRole::CLOUD_TEMPLATED) + .value::Ptr>(); + qDebug() << "Extracting " + << selected_item_index_map_.value(input_cloud_item)->indices.size() + << " points out of " << input_cloud->width; + filter.setInputCloud(input_cloud); + filter.setIndices(selected_item_index_map_.value(input_cloud_item)); + typename PointCloud::Ptr original_minus_indices(new PointCloud); + filter.setNegative(true); + filter.filter(*original_minus_indices); + filter.setNegative(false); + typename PointCloud::Ptr selected_points(new PointCloud); + filter.filter(*selected_points); + + qDebug() << "Original minus indices is " << original_minus_indices->width; - foreach (const CloudItem* input_cloud_item, selected_item_index_map_.keys ()) - { - input_cloud_item->printNumPoints (); - //If this cloud hasn't been completely selected - if (!input_data.contains (input_cloud_item)) - { - typename PointCloud::Ptr input_cloud = input_cloud_item->data (ItemDataRole::CLOUD_TEMPLATED).value ::Ptr> (); - qDebug () << "Extracting "<indices.size() << " points out of "<width; - filter.setInputCloud (input_cloud); - filter.setIndices (selected_item_index_map_.value (input_cloud_item)); - typename PointCloud::Ptr original_minus_indices (new PointCloud); - filter.setNegative (true); - filter.filter (*original_minus_indices); - filter.setNegative (false); - typename PointCloud::Ptr selected_points (new PointCloud); - filter.filter (*selected_points); - - qDebug () << "Original minus indices is "<width; - - CloudItem* new_cloud_item = CloudItem::createCloudItemFromTemplate(input_cloud_item->text (),original_minus_indices); - - output.append (new_cloud_item); + CloudItem* new_cloud_item = CloudItem::createCloudItemFromTemplate( + input_cloud_item->text(), original_minus_indices); + + output.append(new_cloud_item); *merged_cloud += *selected_points; } - //Append the input item to the original list - //input_data.append (input_cloud_item); + // Append the input item to the original list + // input_data.append (input_cloud_item); } - //Just concatenate for all fully selected clouds - foreach (const CloudComposerItem* input_item, input_data) - { - typename PointCloud::Ptr input_cloud = input_item->data (ItemDataRole::CLOUD_TEMPLATED).value ::Ptr> (); + // Just concatenate for all fully selected clouds + foreach (const CloudComposerItem* input_item, input_data) { + typename PointCloud::Ptr input_cloud = + input_item->data(ItemDataRole::CLOUD_TEMPLATED) + .value::Ptr>(); *merged_cloud += *input_cloud; } - CloudItem* cloud_item = CloudItem::createCloudItemFromTemplate("Cloud from Selection",merged_cloud); - - output.append (cloud_item); - - return output; - -} + CloudItem* cloud_item = CloudItem::createCloudItemFromTemplate( + "Cloud from Selection", merged_cloud); + output.append(cloud_item); -#define PCL_INSTANTIATE_performTemplatedAction(T) template void pcl::cloud_composer::MergeSelection::performTemplatedAction (QList ); - + return output; +} +#define PCL_INSTANTIATE_performTemplatedAction(T) \ + template void pcl::cloud_composer::MergeSelection::performTemplatedAction( \ + QList); -#endif //IMPL_MERGE_SELECTION_H_ +#endif // IMPL_MERGE_SELECTION_H_ diff --git a/apps/cloud_composer/include/pcl/apps/cloud_composer/impl/transform_clouds.hpp b/apps/cloud_composer/include/pcl/apps/cloud_composer/impl/transform_clouds.hpp index 92574aec..5fce284b 100644 --- a/apps/cloud_composer/include/pcl/apps/cloud_composer/impl/transform_clouds.hpp +++ b/apps/cloud_composer/include/pcl/apps/cloud_composer/impl/transform_clouds.hpp @@ -1,4 +1,4 @@ - /* +/* * Software License Agreement (BSD License) * * Point Cloud Library (PCL) - www.pointclouds.org @@ -38,61 +38,61 @@ #ifndef IMPL_TRANSFORM_CLOUDS_HPP_ #define IMPL_TRANSFORM_CLOUDS_HPP_ -#include #include -#include +#include #include +#include -template QList -pcl::cloud_composer::TransformClouds::performTemplatedAction (const QList & input_data) +template +QList +pcl::cloud_composer::TransformClouds::performTemplatedAction( + const QList& input_data) { - QList output; - - foreach (const CloudComposerItem* input_item, input_data) - { - QVariant variant = input_item->data (ItemDataRole::CLOUD_TEMPLATED); - if ( ! variant.canConvert ::Ptr> () ) - { - qWarning () << "Attempted to cast to template type which does not exist in this item! (input list)"; + QList output; + + foreach (const CloudComposerItem* input_item, input_data) { + QVariant variant = input_item->data(ItemDataRole::CLOUD_TEMPLATED); + if (!variant.canConvert::Ptr>()) { + qWarning() << "Attempted to cast to template type which does not exist in this " + "item! (input list)"; return output; } - if (!transform_map_.contains ("AllSelectedClouds") && !transform_map_.contains (input_item->getId ())) - { - qCritical () << "No transform found for id "<getId ()<<" in TransformClouds::performTemplatedAction"; + if (!transform_map_.contains("AllSelectedClouds") && + !transform_map_.contains(input_item->getId())) { + qCritical() << "No transform found for id " << input_item->getId() + << " in TransformClouds::performTemplatedAction"; return output; } } - - foreach (const CloudComposerItem* input_item, input_data) - { - qDebug () << "Transforming cloud "<getId (); - QVariant variant = input_item->data (ItemDataRole::CLOUD_TEMPLATED); - typename PointCloud ::Ptr input_cloud = variant.value ::Ptr> (); - + + foreach (const CloudComposerItem* input_item, input_data) { + qDebug() << "Transforming cloud " << input_item->getId(); + QVariant variant = input_item->data(ItemDataRole::CLOUD_TEMPLATED); + typename PointCloud::Ptr input_cloud = + variant.value::Ptr>(); + Eigen::Matrix4f transform; - if (transform_map_.contains ("AllSelectedClouds")) - pcl::visualization::PCLVisualizer::convertToEigenMatrix (transform_map_.value ("AllSelectedClouds"), transform); + if (transform_map_.contains("AllSelectedClouds")) + pcl::visualization::PCLVisualizer::convertToEigenMatrix( + transform_map_.value("AllSelectedClouds"), transform); else - pcl::visualization::PCLVisualizer::convertToEigenMatrix (transform_map_.value (input_item->getId ()), transform); - - typename PointCloud::Ptr transformed_cloud (new PointCloud); - - transformPointCloud (*input_cloud, *transformed_cloud, transform); - CloudItem* new_cloud_item = CloudItem::createCloudItemFromTemplate(input_item->text (),transformed_cloud); - - output.append (new_cloud_item); - } + pcl::visualization::PCLVisualizer::convertToEigenMatrix( + transform_map_.value(input_item->getId()), transform); + + typename PointCloud::Ptr transformed_cloud(new PointCloud); - + transformPointCloud(*input_cloud, *transformed_cloud, transform); + CloudItem* new_cloud_item = CloudItem::createCloudItemFromTemplate( + input_item->text(), transformed_cloud); + output.append(new_cloud_item); + } return output; - } +#define PCL_INSTANTIATE_performTemplatedAction(T) \ + template void pcl::cloud_composer::TransformClouds::performTemplatedAction( \ + QList); -#define PCL_INSTANTIATE_performTemplatedAction(T) template void pcl::cloud_composer::TransformClouds::performTemplatedAction (QList ); - - - -#endif //IMPL_TRANSFORM_CLOUDS_HPP_ +#endif // IMPL_TRANSFORM_CLOUDS_HPP_ diff --git a/apps/cloud_composer/include/pcl/apps/cloud_composer/item_inspector.h b/apps/cloud_composer/include/pcl/apps/cloud_composer/item_inspector.h index dcf7f78c..f03ab1e8 100644 --- a/apps/cloud_composer/include/pcl/apps/cloud_composer/item_inspector.h +++ b/apps/cloud_composer/include/pcl/apps/cloud_composer/item_inspector.h @@ -37,65 +37,58 @@ #pragma once -#include - #include #include +#include + class QItemSelectionModel; class QTreeView; -namespace pcl -{ - namespace cloud_composer - { - /** \brief View class for displaying properties of an item - * \author Jeremie Papon - * \ingroup cloud_composer - */ - class ItemInspector : public QTabWidget - { - Q_OBJECT - public: - ItemInspector (QWidget* parent = nullptr); - - public Q_SLOTS: - void - setModel (ProjectModel* new_model); - void - selectionChanged (const QModelIndex ¤t, const QModelIndex &previous); - void - itemChanged (QStandardItem* item); - - - - private: - void - createItemWidgets (); - /** \brief Stores the state of the current tree view in item_treestate_map_ */ - void - storeTreeState (); - /** \brief Restores the state of \param model 's view from item_treestate_map_ */ - void - restoreTreeState (); - /** \brief Removes the extra tabs the item might have */ - void - removeTabs (); - /** \brief Refreshes the data shown in the current displayed view widget */ - void - updateView (); - - //! The tree object used to display/edit parameters - QTreeView* parameter_view_; - - - ProjectModel* current_project_model_; - PropertiesModel* current_item_properties_model_; - const QItemSelectionModel *current_selection_model_; - QMap itemtype_widget_map; - QMap > item_treestate_map_; - }; - - - } -} +namespace pcl { +namespace cloud_composer { +/** \brief View class for displaying properties of an item + * \author Jeremie Papon + * \ingroup cloud_composer + */ +class ItemInspector : public QTabWidget { + Q_OBJECT +public: + ItemInspector(QWidget* parent = nullptr); + +public Q_SLOTS: + void + setModel(ProjectModel* new_model); + void + selectionChanged(const QModelIndex& current, const QModelIndex& previous); + void + itemChanged(QStandardItem* item); + +private: + void + createItemWidgets(); + /** \brief Stores the state of the current tree view in item_treestate_map_ */ + void + storeTreeState(); + /** \brief Restores the state of \param model 's view from item_treestate_map_ */ + void + restoreTreeState(); + /** \brief Removes the extra tabs the item might have */ + void + removeTabs(); + /** \brief Refreshes the data shown in the current displayed view widget */ + void + updateView(); + + //! The tree object used to display/edit parameters + QTreeView* parameter_view_; + + ProjectModel* current_project_model_; + PropertiesModel* current_item_properties_model_; + const QItemSelectionModel* current_selection_model_; + QMap itemtype_widget_map; + QMap> item_treestate_map_; +}; + +} // namespace cloud_composer +} // namespace pcl diff --git a/apps/cloud_composer/include/pcl/apps/cloud_composer/items/cloud_composer_item.h b/apps/cloud_composer/include/pcl/apps/cloud_composer/items/cloud_composer_item.h index 07f9bc10..422f8e3d 100644 --- a/apps/cloud_composer/include/pcl/apps/cloud_composer/items/cloud_composer_item.h +++ b/apps/cloud_composer/include/pcl/apps/cloud_composer/items/cloud_composer_item.h @@ -37,128 +37,133 @@ #pragma once -#include -#include #include +#include +#include + +static QStringList ITEM_TYPES_STRINGS(QStringList() << "Cloud Composer Item" + << "Cloud Item" + << "Normals Item" + << "FPFH Item"); -static QStringList ITEM_TYPES_STRINGS(QStringList() - << "Cloud Composer Item" - << "Cloud Item" - << "Normals Item" - << "FPFH Item" - ); +namespace pcl { +namespace cloud_composer { +class PropertiesModel; +namespace ItemDataRole { +enum { + PROPERTIES = Qt::UserRole, + ITEM_ID, + CLOUD_BLOB, + CLOUD_TEMPLATED, + GEOMETRY_HANDLER, + COLOR_HANDLER, + ORIGIN, + ORIENTATION, + KD_TREE_SEARCH +}; +}; +class CloudComposerItem : public QStandardItem { +public: + enum ItemType { + CLOUD_COMPOSER_ITEM = QStandardItem::UserType, + CLOUD_ITEM, + NORMALS_ITEM, + FPFH_ITEM + }; + + CloudComposerItem(const QString& name = "default item"); + CloudComposerItem(const CloudComposerItem& to_copy); + ~CloudComposerItem(); + + inline int + type() const override + { + return CLOUD_COMPOSER_ITEM; + } -namespace pcl -{ - namespace cloud_composer + /** \brief Convenience function to get Item's ID String */ + inline QString + getId() const { - class PropertiesModel; - namespace ItemDataRole - { - enum - { - PROPERTIES = Qt::UserRole, - ITEM_ID, - CLOUD_BLOB, - CLOUD_TEMPLATED, - GEOMETRY_HANDLER, - COLOR_HANDLER, - ORIGIN, - ORIENTATION, - KD_TREE_SEARCH - }; - }; - class CloudComposerItem : public QStandardItem - { - public: - - - enum ItemType - { - CLOUD_COMPOSER_ITEM = QStandardItem::UserType, - CLOUD_ITEM, - NORMALS_ITEM, - FPFH_ITEM - }; - - CloudComposerItem (const QString& name = "default item"); - CloudComposerItem (const CloudComposerItem& to_copy); - ~CloudComposerItem (); - - inline int - type () const override { return CLOUD_COMPOSER_ITEM; } - - /** \brief Convenience function to get Item's ID String */ - inline QString - getId () const { return data (ItemDataRole::ITEM_ID).toString (); } - - /** \brief Convenience function to get Item's Property Pointer */ - inline PropertiesModel* - getPropertiesModel () const { return properties_; } - - /** \brief Returns all children of item type type*/ - QList - getChildren (ItemType type) const; - - void - addChild (CloudComposerItem* item_arg); - - CloudComposerItem* - clone () const override; - - // /** \brief Convenience function which pulls out a cloud Ptr of type CloudPtrT */ - // template - // CloudPtrT - // getCloudPtr () const; - - /** \brief Paint View function - reimplement in item subclass if it can be displayed in PCLVisualizer*/ - virtual void - paintView (pcl::visualization::PCLVisualizer::Ptr vis) const; - - /** \brief Remove from View function - reimplement in item subclass if it can be displayed in PCLVisualizer*/ - virtual void - removeFromView (pcl::visualization::PCLVisualizer::Ptr vis) const; - - /** \brief Inspector additional tabs paint function - reimplement in item subclass if item has additional tabs to show in Inspector*/ - virtual QMap - getInspectorTabs (); - - /** \brief The property model calls this when a property changes */ - inline void - propertyChanged () - { - emitDataChanged (); - } - - virtual bool - isSanitized () const { return false; } - protected: - - /** \brief Model for storing the properties of the item - pointer kept for convenience */ - PropertiesModel* properties_; - - }; - - - - /** \brief Templated helper class for converting QVariant to/from pointer classes */ - template class VPtr - { - public: - static T* asPtr (const QVariant& v) - { - return (static_cast (v.value ())); - } - - static QVariant asQVariant (T* ptr) - { - return (QVariant::fromValue (static_cast(ptr))); - } - }; - + return data(ItemDataRole::ITEM_ID).toString(); } -} -using ConstItemList = QList; + /** \brief Convenience function to get Item's Property Pointer */ + inline PropertiesModel* + getPropertiesModel() const + { + return properties_; + } + + /** \brief Returns all children of item type type*/ + QList + getChildren(ItemType type) const; + + void + addChild(CloudComposerItem* item_arg); + + CloudComposerItem* + clone() const override; + + // /** \brief Convenience function which pulls out a cloud Ptr of type CloudPtrT */ + // template + // CloudPtrT + // getCloudPtr () const; + + /** \brief Paint View function - reimplement in item subclass if it can be displayed + * in PCLVisualizer*/ + virtual void + paintView(pcl::visualization::PCLVisualizer::Ptr vis) const; + + /** \brief Remove from View function - reimplement in item subclass if it can be + * displayed in PCLVisualizer*/ + virtual void + removeFromView(pcl::visualization::PCLVisualizer::Ptr vis) const; + + /** \brief Inspector additional tabs paint function - reimplement in item subclass if + * item has additional tabs to show in Inspector*/ + virtual QMap + getInspectorTabs(); + + /** \brief The property model calls this when a property changes */ + inline void + propertyChanged() + { + emitDataChanged(); + } + + virtual bool + isSanitized() const + { + return false; + } + +protected: + /** \brief Model for storing the properties of the item - pointer kept for convenience + */ + PropertiesModel* properties_; +}; + +/** \brief Templated helper class for converting QVariant to/from pointer classes */ +template +class VPtr { +public: + static T* + asPtr(const QVariant& v) + { + return (static_cast(v.value())); + } + + static QVariant + asQVariant(T* ptr) + { + return (QVariant::fromValue(static_cast(ptr))); + } +}; + +} // namespace cloud_composer +} // namespace pcl + +using ConstItemList = QList; -Q_DECLARE_METATYPE (pcl::cloud_composer::CloudComposerItem); +Q_DECLARE_METATYPE(pcl::cloud_composer::CloudComposerItem); diff --git a/apps/cloud_composer/include/pcl/apps/cloud_composer/items/cloud_item.h b/apps/cloud_composer/include/pcl/apps/cloud_composer/items/cloud_item.h index aabf5aab..8e4a6a4b 100644 --- a/apps/cloud_composer/include/pcl/apps/cloud_composer/items/cloud_item.h +++ b/apps/cloud_composer/include/pcl/apps/cloud_composer/items/cloud_item.h @@ -37,162 +37,171 @@ #pragma once -#include - #include - -#include -#include -#include -#include -#include #include -#include -#include #include +#include +#include +#include +#include +#include +#include +#include +#include -//Typedefs to make things sane -using GeometryHandler = pcl::visualization::PointCloudGeometryHandler; +// Typedefs to make things sane +using GeometryHandler = + pcl::visualization::PointCloudGeometryHandler; using ColorHandler = pcl::visualization::PointCloudColorHandler; -namespace pcl -{ - namespace cloud_composer +namespace pcl { +namespace cloud_composer { +namespace PointTypeFlags { +enum PointType { + NONE = 0, + XYZ = (1 << 0), + RGB = (1 << 1), + RGBA = (1 << 2), + NORMAL = (1 << 3), + HSV = (1 << 4), + AXIS = (1 << 5), +}; +} +class CloudItem : public CloudComposerItem { +public: + // This is needed because we have members which are Vector4f and Quaternionf + PCL_MAKE_ALIGNED_OPERATOR_NEW + + CloudItem(const QString name, + const pcl::PCLPointCloud2::Ptr& cloud_ptr, + const Eigen::Vector4f& origin = Eigen::Vector4f(), + const Eigen::Quaternionf& orientation = Eigen::Quaternionf(), + bool make_templated_cloud = true); + + CloudItem(const CloudItem& to_copy); + + /** \brief This creates a CloudItem from a templated cloud type */ + template + static CloudItem* + createCloudItemFromTemplate(const QString& name, + typename PointCloud::Ptr cloud_ptr); + + /** \brief virtual data getter which calls QStandardItem::data; used to create + * template cloud if not created yet WARNING : This function modifies "this" - it sets + * up the templated type if you request one when it doesn't exist yet! It had to + * remain const because it is virtual, and we need to keep run-time polymorphism + */ + QVariant + data(int role = Qt::UserRole + 1) const override; + + /** \brief Virtual data setter which calls QStandardItem::data; used to ensure that + * template_cloud_set_ is set when a templated cloud is added */ + void + setData(const QVariant& value, int role = Qt::UserRole + 1) override; + + inline int + type() const override { - namespace PointTypeFlags - { - enum PointType - { - NONE = 0, - XYZ = (1 << 0), - RGB = (1 << 1), - RGBA = (1 << 2), - NORMAL = (1 << 3), - HSV = (1 << 4), - AXIS = (1 << 5), - }; - } - class CloudItem : public CloudComposerItem - { - public: - - //This is needed because we have members which are Vector4f and Quaternionf - PCL_MAKE_ALIGNED_OPERATOR_NEW - - CloudItem (const QString name, - const pcl::PCLPointCloud2::Ptr& cloud_ptr, - const Eigen::Vector4f& origin = Eigen::Vector4f (), - const Eigen::Quaternionf& orientation = Eigen::Quaternionf (), - bool make_templated_cloud = true); - - CloudItem (const CloudItem& to_copy); - - /** \brief This creates a CloudItem from a templated cloud type */ - template - static CloudItem* - createCloudItemFromTemplate (const QString& name, typename PointCloud::Ptr cloud_ptr); - - /** \brief virtual data getter which calls QStandardItem::data; used to create template cloud if not created yet - * WARNING : This function modifies "this" - it sets up the templated type if you request one when it doesn't exist yet! - * It had to remain const because it is virtual, and we need to keep run-time polymorphism - */ - QVariant - data (int role = Qt::UserRole +1) const override; - - /** \brief Virtual data setter which calls QStandardItem::data; used to ensure that template_cloud_set_ is set - * when a templated cloud is added */ - void - setData ( const QVariant & value, int role = Qt::UserRole + 1 ) override; - - inline int - type () const override { return CLOUD_ITEM; } - - CloudItem* - clone () const override; - - /** \brief Paint View function - puts this cloud item into a PCLVisualizer object*/ - void - paintView (pcl::visualization::PCLVisualizer::Ptr vis) const override; - - /** \brief Remove from View function - removes this cloud from a PCLVisualizer object*/ - void - removeFromView (pcl::visualization::PCLVisualizer::Ptr vis) const override; - - /** \brief Initializes and stores a templated PointCloud object with point type matching the blob */ - void - setTemplateCloudFromBlob (); - - int - getPointType () const { return point_type_; } - - template void - printNumPoints () const; - - bool - isSanitized () const override { return is_sanitized_; } - private: - - //These are just stored for convenience - pcl::PCLPointCloud2::Ptr cloud_blob_ptr_; - ColorHandler::ConstPtr color_handler_; - GeometryHandler::ConstPtr geometry_handler_; - - //We keep actual local copies of these. - Eigen::Vector4f origin_; - Eigen::Quaternionf orientation_; - - bool template_cloud_set_; - - //Internal Storage of the templated type of this cloud - int point_type_; - - bool - checkIfFinite (); - - bool is_sanitized_; - - //Helper functions which set the point_type_ based on the current point type - template inline void - setPointType () - { - qCritical () << "CloudItem::setPointType for type with no specialization"; - point_type_ = PointTypeFlags::NONE; - } - - }; - - template <> inline void - CloudItem::setPointType () - { - point_type_ = PointTypeFlags::XYZ; - } - template <> inline void - CloudItem::setPointType () - { - point_type_ = PointTypeFlags::XYZ | PointTypeFlags::RGB; - } - template <> inline void - CloudItem::setPointType () - { - point_type_ = PointTypeFlags::XYZ | PointTypeFlags::RGBA; - } - - + return CLOUD_ITEM; } + + CloudItem* + clone() const override; + + /** \brief Paint View function - puts this cloud item into a PCLVisualizer object*/ + void + paintView(pcl::visualization::PCLVisualizer::Ptr vis) const override; + + /** \brief Remove from View function - removes this cloud from a PCLVisualizer + * object*/ + void + removeFromView(pcl::visualization::PCLVisualizer::Ptr vis) const override; + + /** \brief Initializes and stores a templated PointCloud object with point type + * matching the blob */ + void + setTemplateCloudFromBlob(); + + int + getPointType() const + { + return point_type_; + } + + template + void + printNumPoints() const; + + bool + isSanitized() const override + { + return is_sanitized_; + } + +private: + // These are just stored for convenience + pcl::PCLPointCloud2::Ptr cloud_blob_ptr_; + ColorHandler::ConstPtr color_handler_; + GeometryHandler::ConstPtr geometry_handler_; + + // We keep actual local copies of these. + Eigen::Vector4f origin_; + Eigen::Quaternionf orientation_; + + bool template_cloud_set_; + + // Internal Storage of the templated type of this cloud + int point_type_; + + bool + checkIfFinite(); + + bool is_sanitized_; + + // Helper functions which set the point_type_ based on the current point type + template + inline void + setPointType() + { + qCritical() << "CloudItem::setPointType for type with no specialization"; + point_type_ = PointTypeFlags::NONE; + } +}; + +template <> +inline void +CloudItem::setPointType() +{ + point_type_ = PointTypeFlags::XYZ; +} +template <> +inline void +CloudItem::setPointType() +{ + point_type_ = PointTypeFlags::XYZ | PointTypeFlags::RGB; } +template <> +inline void +CloudItem::setPointType() +{ + point_type_ = PointTypeFlags::XYZ | PointTypeFlags::RGBA; +} + +} // namespace cloud_composer +} // namespace pcl -//Add PointCloud types to QT MetaType System -Q_DECLARE_METATYPE (pcl::PCLPointCloud2::ConstPtr); -Q_DECLARE_METATYPE (GeometryHandler::ConstPtr); -Q_DECLARE_METATYPE (ColorHandler::ConstPtr); -Q_DECLARE_METATYPE (Eigen::Vector4f); -Q_DECLARE_METATYPE (Eigen::Quaternionf); +// Add PointCloud types to QT MetaType System +Q_DECLARE_METATYPE(pcl::PCLPointCloud2::ConstPtr); +Q_DECLARE_METATYPE(GeometryHandler::ConstPtr); +Q_DECLARE_METATYPE(ColorHandler::ConstPtr); +Q_DECLARE_METATYPE(Eigen::Vector4f); +Q_DECLARE_METATYPE(Eigen::Quaternionf); -Q_DECLARE_METATYPE (pcl::search::KdTree::Ptr); -Q_DECLARE_METATYPE (pcl::search::KdTree::Ptr); -Q_DECLARE_METATYPE (pcl::search::KdTree::Ptr); +Q_DECLARE_METATYPE(pcl::search::KdTree::Ptr); +Q_DECLARE_METATYPE(pcl::search::KdTree::Ptr); +Q_DECLARE_METATYPE(pcl::search::KdTree::Ptr); -Q_DECLARE_METATYPE (pcl::PointCloud ::Ptr); -Q_DECLARE_METATYPE (pcl::PointCloud ::Ptr); -Q_DECLARE_METATYPE (pcl::PointCloud ::Ptr); +Q_DECLARE_METATYPE(pcl::PointCloud::Ptr); +Q_DECLARE_METATYPE(pcl::PointCloud::Ptr); +Q_DECLARE_METATYPE(pcl::PointCloud::Ptr); diff --git a/apps/cloud_composer/include/pcl/apps/cloud_composer/items/fpfh_item.h b/apps/cloud_composer/include/pcl/apps/cloud_composer/items/fpfh_item.h index 5a634272..e1241504 100644 --- a/apps/cloud_composer/include/pcl/apps/cloud_composer/items/fpfh_item.h +++ b/apps/cloud_composer/include/pcl/apps/cloud_composer/items/fpfh_item.h @@ -37,47 +37,45 @@ #pragma once -#include -#include - #include -#include +#include #include +#include +#include + +namespace pcl { +namespace cloud_composer { + +class FPFHItem : public CloudComposerItem { +public: + FPFHItem(QString name, + const pcl::PointCloud::Ptr& fpfh_ptr, + double radius); + FPFHItem(const FPFHItem& to_copy); -namespace pcl -{ - namespace cloud_composer + inline int + type() const override { - - class FPFHItem : public CloudComposerItem - { - public: + return FPFH_ITEM; + } - FPFHItem (QString name, - const pcl::PointCloud::Ptr& fpfh_ptr, - double radius); - FPFHItem (const FPFHItem& to_copy); - - inline int - type () const override { return FPFH_ITEM; } + FPFHItem* + clone() const override; - FPFHItem* - clone () const override; - - /** \brief Inspector additional tabs paint function - get the histogram plot widget*/ - QMap - getInspectorTabs () override; - - private: - pcl::PointCloud::Ptr fpfh_ptr_; - double radius_; - pcl::visualization::PCLPlotter::Ptr plot_; - PCLQVTKWidget* qvtk_; - QWidget *hist_page_; - }; + /** \brief Inspector additional tabs paint function - get the histogram plot widget*/ + QMap + getInspectorTabs() override; - } -} +private: + pcl::PointCloud::Ptr fpfh_ptr_; + double radius_; + pcl::visualization::PCLPlotter::Ptr plot_; + PCLQVTKWidget* qvtk_; + QWidget* hist_page_; +}; + +} // namespace cloud_composer +} // namespace pcl -Q_DECLARE_METATYPE (pcl::PointCloud::Ptr); -Q_DECLARE_METATYPE (pcl::PointCloud::ConstPtr); +Q_DECLARE_METATYPE(pcl::PointCloud::Ptr); +Q_DECLARE_METATYPE(pcl::PointCloud::ConstPtr); diff --git a/apps/cloud_composer/include/pcl/apps/cloud_composer/items/normals_item.h b/apps/cloud_composer/include/pcl/apps/cloud_composer/items/normals_item.h index 73c687bd..40fb5c3c 100644 --- a/apps/cloud_composer/include/pcl/apps/cloud_composer/items/normals_item.h +++ b/apps/cloud_composer/include/pcl/apps/cloud_composer/items/normals_item.h @@ -37,47 +37,43 @@ #pragma once -#include +#include #include +#include -#include +namespace pcl { +namespace cloud_composer { + +class NormalsItem : public CloudComposerItem { +public: + NormalsItem(QString name, + const pcl::PointCloud::Ptr& normals_ptr, + double radius); + NormalsItem(const NormalsItem& to_copy); -namespace pcl -{ - namespace cloud_composer + inline int + type() const override { - - class NormalsItem : public CloudComposerItem - { - public: + return NORMALS_ITEM; + } - NormalsItem (QString name, - const pcl::PointCloud::Ptr& normals_ptr, - double radius); - NormalsItem (const NormalsItem& to_copy); - - inline int - type () const override { return NORMALS_ITEM; } + NormalsItem* + clone() const override; - NormalsItem* - clone () const override; - - void - paintView (pcl::visualization::PCLVisualizer::Ptr vis) const override; - - /** \brief Remove from View function - removes the normal cloud from a PCLVisualizer object*/ - void - removeFromView (pcl::visualization::PCLVisualizer::Ptr vis) const override; - - private: - pcl::PointCloud::Ptr normals_ptr_; + void + paintView(pcl::visualization::PCLVisualizer::Ptr vis) const override; - }; - - - - } -} + /** \brief Remove from View function - removes the normal cloud from a PCLVisualizer + * object*/ + void + removeFromView(pcl::visualization::PCLVisualizer::Ptr vis) const override; + +private: + pcl::PointCloud::Ptr normals_ptr_; +}; + +} // namespace cloud_composer +} // namespace pcl -Q_DECLARE_METATYPE (pcl::PointCloud::Ptr); -Q_DECLARE_METATYPE (pcl::PointCloud::ConstPtr); +Q_DECLARE_METATYPE(pcl::PointCloud::Ptr); +Q_DECLARE_METATYPE(pcl::PointCloud::ConstPtr); diff --git a/apps/cloud_composer/include/pcl/apps/cloud_composer/merge_selection.h b/apps/cloud_composer/include/pcl/apps/cloud_composer/merge_selection.h index af3d7afa..0e4181c3 100644 --- a/apps/cloud_composer/include/pcl/apps/cloud_composer/merge_selection.h +++ b/apps/cloud_composer/include/pcl/apps/cloud_composer/merge_selection.h @@ -39,31 +39,38 @@ #include -namespace pcl -{ - namespace cloud_composer +namespace pcl { +namespace cloud_composer { +class MergeSelection : public MergeCloudTool { + Q_OBJECT +public: + MergeSelection( + QMap selected_item_index_map, + QObject* parent = nullptr); + + QList + performAction(QList input_data, + PointTypeFlags::PointType type = PointTypeFlags::NONE) override; + + inline QString + getToolName() const override { - class MergeSelection : public MergeCloudTool - { - Q_OBJECT - public: - MergeSelection (QMap selected_item_index_map, QObject* parent = nullptr); - - QList - performAction (QList input_data, PointTypeFlags::PointType type = PointTypeFlags::NONE) override; - - inline QString - getToolName () const override { return "Merge Selection Tool";} - - QList - getSelectedItems () { return selected_item_index_map_.keys ();} - - template QList - performTemplatedAction (const QList & input_data); - - private: - QMap selected_item_index_map_; - }; + return "Merge Selection Tool"; + } + QList + getSelectedItems() + { + return selected_item_index_map_.keys(); } -} + + template + QList + performTemplatedAction(const QList& input_data); + +private: + QMap selected_item_index_map_; +}; + +} // namespace cloud_composer +} // namespace pcl diff --git a/apps/cloud_composer/include/pcl/apps/cloud_composer/point_selectors/click_trackball_interactor_style.h b/apps/cloud_composer/include/pcl/apps/cloud_composer/point_selectors/click_trackball_interactor_style.h index 2477b33b..7bb9d3fa 100644 --- a/apps/cloud_composer/include/pcl/apps/cloud_composer/point_selectors/click_trackball_interactor_style.h +++ b/apps/cloud_composer/include/pcl/apps/cloud_composer/point_selectors/click_trackball_interactor_style.h @@ -41,73 +41,83 @@ #include -namespace pcl -{ - namespace cloud_composer +namespace pcl { +namespace cloud_composer { + +class ClickTrackballStyleInteractor : public vtkInteractorStyleTrackballActor { +public: + static ClickTrackballStyleInteractor* + New(); + vtkTypeMacro(ClickTrackballStyleInteractor, vtkInteractorStyleTrackballActor); + + ClickTrackballStyleInteractor(); + + /** \brief Pass a pointer to the actor map + * \param[in] actors the actor map that will be used with this style + */ + inline void + setCloudActorMap(const pcl::visualization::CloudActorMapPtr& actors) + { + actors_ = actors; + } + + /** \brief Get the cloud actor map pointer. */ + inline pcl::visualization::CloudActorMapPtr + getCloudActorMap() const + { + return (actors_); + } + + /** \brief Pass a set of renderers to the interactor style. + * \param[in] rens the vtkRendererCollection to use + */ + void + setRendererCollection(vtkSmartPointer& rens) + { + renderers_ = rens; + } + + /** \brief Function called on left mouse button release, ie, end of rectangular drag + */ + void + OnLeftButtonDown() override; + + /** \brief Function called on left mouse button release, ie, end of rectangular drag + */ + void + OnLeftButtonUp() override; + + void + OnRightButtonDown() override; + + void + OnRightButtonUp() override; + + /** \brief Event emitted once a valid selection has been made */ + int manipulation_complete_event_; + + inline void + setProjectModel(ProjectModel* model) { - - class ClickTrackballStyleInteractor : public vtkInteractorStyleTrackballActor - { - public: - static ClickTrackballStyleInteractor* New(); - vtkTypeMacro(ClickTrackballStyleInteractor,vtkInteractorStyleTrackballActor); - - ClickTrackballStyleInteractor (); - - /** \brief Pass a pointer to the actor map - * \param[in] actors the actor map that will be used with this style - */ - inline void - setCloudActorMap (const pcl::visualization::CloudActorMapPtr &actors) { actors_ = actors; } - - /** \brief Get the cloud actor map pointer. */ - inline pcl::visualization::CloudActorMapPtr - getCloudActorMap () const { return (actors_); } - - /** \brief Pass a set of renderers to the interactor style. - * \param[in] rens the vtkRendererCollection to use - */ - void - setRendererCollection (vtkSmartPointer &rens) { renderers_ = rens; } - - /** \brief Function called on left mouse button release, ie, end of rectangular drag */ - void - OnLeftButtonDown () override; - - /** \brief Function called on left mouse button release, ie, end of rectangular drag */ - void - OnLeftButtonUp () override; - - void - OnRightButtonDown () override; - - void - OnRightButtonUp () override; - - /** \brief Event emitted once a valid selection has been made */ - int manipulation_complete_event_; - - inline void - setProjectModel (ProjectModel* model) { model_ = model; } - private: - - - /** \brief Actor map stored internally. */ - pcl::visualization::CloudActorMapPtr actors_; - - /** \brief Collection of vtkRenderers stored internally. */ - vtkSmartPointer renderers_; - - /** \brief Internal Pointer to Project Model */ - ProjectModel* model_; - - vtkSmartPointer start_matrix_; - vtkSmartPointer end_matrix_; - - vtkSmartPointer transform_; - - }; - + model_ = model; } - -} + +private: + /** \brief Actor map stored internally. */ + pcl::visualization::CloudActorMapPtr actors_; + + /** \brief Collection of vtkRenderers stored internally. */ + vtkSmartPointer renderers_; + + /** \brief Internal Pointer to Project Model */ + ProjectModel* model_; + + vtkSmartPointer start_matrix_; + vtkSmartPointer end_matrix_; + + vtkSmartPointer transform_; +}; + +} // namespace cloud_composer + +} // namespace pcl diff --git a/apps/cloud_composer/include/pcl/apps/cloud_composer/point_selectors/interactor_style_switch.h b/apps/cloud_composer/include/pcl/apps/cloud_composer/point_selectors/interactor_style_switch.h index 1f4fcd17..f7905862 100644 --- a/apps/cloud_composer/include/pcl/apps/cloud_composer/point_selectors/interactor_style_switch.h +++ b/apps/cloud_composer/include/pcl/apps/cloud_composer/point_selectors/interactor_style_switch.h @@ -37,118 +37,122 @@ #pragma once -#include - -#include #include #include +#include #include -#include +#include + #include -#include -#include #include -#include #include +#include +#include +#include +#include class QVTKWidget; -namespace pcl -{ - namespace cloud_composer +namespace pcl { +namespace cloud_composer { +namespace interactor_styles { +enum INTERACTOR_STYLES { + PCL_VISUALIZER = 0, + RECTANGULAR_FRUSTUM, + SELECTED_TRACKBALL, + CLICK_TRACKBALL +}; +} +namespace interactor_events { +enum { + SELECTION_COMPLETE_EVENT = vtkCommand::UserEvent + 1, + MANIPULATION_COMPLETE_EVENT +}; +}; + +class RectangularFrustumSelector; +class SelectedTrackballStyleInteractor; +class ClickTrackballStyleInteractor; +class ProjectModel; + +class InteractorStyleSwitch : public vtkInteractorStyle { +public: + static InteractorStyleSwitch* + New(); + vtkTypeMacro(InteractorStyleSwitch, vtkInteractorStyle); + + InteractorStyleSwitch(); + + void + SetInteractor(vtkRenderWindowInteractor* iren) override; + + vtkGetObjectMacro(current_style_, vtkInteractorStyle); + + void + initializeInteractorStyles(pcl::visualization::PCLVisualizer::Ptr vis, + ProjectModel* model); + + inline void + setQVTKWidget(QVTKWidget* qvtk) { - namespace interactor_styles - { - enum INTERACTOR_STYLES - { - PCL_VISUALIZER = 0, - RECTANGULAR_FRUSTUM, - SELECTED_TRACKBALL, - CLICK_TRACKBALL - }; - } - namespace interactor_events - { - enum - { - SELECTION_COMPLETE_EVENT = vtkCommand::UserEvent + 1, - MANIPULATION_COMPLETE_EVENT - }; - }; - - class RectangularFrustumSelector; - class SelectedTrackballStyleInteractor; - class ClickTrackballStyleInteractor; - class ProjectModel; - - class InteractorStyleSwitch : public vtkInteractorStyle - { - public: - static InteractorStyleSwitch *New(); - vtkTypeMacro(InteractorStyleSwitch, vtkInteractorStyle); - - InteractorStyleSwitch(); - - void - SetInteractor(vtkRenderWindowInteractor *iren) override; - - vtkGetObjectMacro(current_style_, vtkInteractorStyle); - - void - initializeInteractorStyles (pcl::visualization::PCLVisualizer::Ptr vis, ProjectModel* model); - - inline void - setQVTKWidget (QVTKWidget* qvtk) { qvtk_ = qvtk; } - - void - setCurrentInteractorStyle (interactor_styles::INTERACTOR_STYLES interactor_style); - - // vtkSmartPointer - // getPCLVisInteractorStyle () { return pcl_vis_style_; } - - inline vtkSmartPointer - getInteractorStyle (const interactor_styles::INTERACTOR_STYLES interactor_style) const - { return name_to_style_map_.value (interactor_style); } - - - void SetDefaultRenderer(vtkRenderer*) override; - - void SetCurrentRenderer(vtkRenderer*) override; - - void - OnLeave () override; - - protected: - void - setCurrentStyle(); - - QMap > name_to_style_map_; - - - vtkRenderWindowInteractor* render_window_interactor_; - vtkSmartPointer rens_; - - vtkInteractorStyle* current_style_; - vtkSmartPointer pcl_vis_style_; - vtkSmartPointer rectangular_frustum_selector_; - - vtkSmartPointer selected_trackball_interactor_style_; - - vtkSmartPointer click_trackball_interactor_style_; - vtkSmartPointer area_picker_; - vtkSmartPointer point_picker_; - - /** \brief Internal pointer to QVTKWidget that this Switch works with */ - QVTKWidget* qvtk_; - /** \brief Internal pointer to PCLVisualizer that this Switch works with */ - pcl::visualization::PCLVisualizer::Ptr vis_; - private: - InteractorStyleSwitch(const InteractorStyleSwitch&); // Not implemented. - void operator=(const InteractorStyleSwitch&); // Not implemented. - ProjectModel* project_model_; - }; - + qvtk_ = qvtk; } - -} + + void + setCurrentInteractorStyle(interactor_styles::INTERACTOR_STYLES interactor_style); + + // vtkSmartPointer + // getPCLVisInteractorStyle () { return pcl_vis_style_; } + + inline vtkSmartPointer + getInteractorStyle(const interactor_styles::INTERACTOR_STYLES interactor_style) const + { + return name_to_style_map_.value(interactor_style); + } + + void + SetDefaultRenderer(vtkRenderer*) override; + + void + SetCurrentRenderer(vtkRenderer*) override; + + void + OnLeave() override; + +protected: + void + setCurrentStyle(); + + QMap> + name_to_style_map_; + + vtkRenderWindowInteractor* render_window_interactor_; + vtkSmartPointer rens_; + + vtkInteractorStyle* current_style_; + vtkSmartPointer pcl_vis_style_; + vtkSmartPointer rectangular_frustum_selector_; + + vtkSmartPointer + selected_trackball_interactor_style_; + + vtkSmartPointer click_trackball_interactor_style_; + vtkSmartPointer area_picker_; + vtkSmartPointer point_picker_; + + /** \brief Internal pointer to QVTKWidget that this Switch works with */ + QVTKWidget* qvtk_; + /** \brief Internal pointer to PCLVisualizer that this Switch works with */ + pcl::visualization::PCLVisualizer::Ptr vis_; + +private: + InteractorStyleSwitch(const InteractorStyleSwitch&); // Not implemented. + void + operator=(const InteractorStyleSwitch&); // Not implemented. + ProjectModel* project_model_; +}; + +} // namespace cloud_composer + +} // namespace pcl diff --git a/apps/cloud_composer/include/pcl/apps/cloud_composer/point_selectors/manipulation_event.h b/apps/cloud_composer/include/pcl/apps/cloud_composer/point_selectors/manipulation_event.h index 73efe79c..af1f09e8 100644 --- a/apps/cloud_composer/include/pcl/apps/cloud_composer/point_selectors/manipulation_event.h +++ b/apps/cloud_composer/include/pcl/apps/cloud_composer/point_selectors/manipulation_event.h @@ -39,35 +39,36 @@ #include -namespace pcl -{ - namespace cloud_composer +namespace pcl { +namespace cloud_composer { + +class ManipulationEvent { + +public: + ManipulationEvent() {} + + void + addManipulation(const QString& id, + const vtkSmartPointer& start, + const vtkSmartPointer& end); + + inline QMap> + getStartMap() const + { + return id_start_map_; + } + + inline QMap> + getEndMap() const { - - - class ManipulationEvent - { - - public: - ManipulationEvent () - {} - - void - addManipulation (const QString& id, const vtkSmartPointer& start, const vtkSmartPointer& end); - - inline QMap > - getStartMap () const { return id_start_map_;} - - inline QMap > - getEndMap () const { return id_end_map_;} - - - private: - QMap > id_start_map_; - QMap > id_end_map_; - - }; - + return id_end_map_; } - -} + +private: + QMap> id_start_map_; + QMap> id_end_map_; +}; + +} // namespace cloud_composer + +} // namespace pcl diff --git a/apps/cloud_composer/include/pcl/apps/cloud_composer/point_selectors/rectangular_frustum_selector.h b/apps/cloud_composer/include/pcl/apps/cloud_composer/point_selectors/rectangular_frustum_selector.h index bed9b5d5..6ad55d6e 100644 --- a/apps/cloud_composer/include/pcl/apps/cloud_composer/point_selectors/rectangular_frustum_selector.h +++ b/apps/cloud_composer/include/pcl/apps/cloud_composer/point_selectors/rectangular_frustum_selector.h @@ -39,55 +39,62 @@ #include -#include -#include #include +#include +#include -namespace pcl -{ - namespace cloud_composer - { - - class RectangularFrustumSelector : public vtkInteractorStyleRubberBandPick - { - public: - static RectangularFrustumSelector* New(); - vtkTypeMacro(RectangularFrustumSelector,vtkInteractorStyleRubberBandPick); - - RectangularFrustumSelector (); - - /** \brief Pass a pointer to the actor map - * \param[in] actors the actor map that will be used with this style - */ - inline void - setCloudActorMap (const pcl::visualization::CloudActorMapPtr &actors) { actors_ = actors; } +namespace pcl { +namespace cloud_composer { - /** \brief Get the cloud actor map pointer. */ - inline pcl::visualization::CloudActorMapPtr - getCloudActorMap () const { return (actors_); } +class RectangularFrustumSelector : public vtkInteractorStyleRubberBandPick { +public: + static RectangularFrustumSelector* + New(); + vtkTypeMacro(RectangularFrustumSelector, vtkInteractorStyleRubberBandPick); - /** \brief Pass a set of renderers to the interactor style. - * \param[in] rens the vtkRendererCollection to use - */ - void - setRendererCollection (vtkSmartPointer &rens) { renderers_ = rens; } + RectangularFrustumSelector(); - /** \brief Function called on left mouse button release, ie, end of rectangular drag */ - void - OnLeftButtonUp () override; + /** \brief Pass a pointer to the actor map + * \param[in] actors the actor map that will be used with this style + */ + inline void + setCloudActorMap(const pcl::visualization::CloudActorMapPtr& actors) + { + actors_ = actors; + } - /** \brief Event emitted once a valid selection has been made */ - int selection_complete_event_; - private: + /** \brief Get the cloud actor map pointer. */ + inline pcl::visualization::CloudActorMapPtr + getCloudActorMap() const + { + return (actors_); + } - - /** \brief Actor map stored internally. */ - pcl::visualization::CloudActorMapPtr actors_; - - /** \brief Collection of vtkRenderers stored internally. */ - vtkSmartPointer renderers_; - }; - + /** \brief Pass a set of renderers to the interactor style. + * \param[in] rens the vtkRendererCollection to use + */ + void + setRendererCollection(vtkSmartPointer& rens) + { + renderers_ = rens; } - -} + + /** \brief Function called on left mouse button release, ie, end of rectangular drag + */ + void + OnLeftButtonUp() override; + + /** \brief Event emitted once a valid selection has been made */ + int selection_complete_event_; + +private: + /** \brief Actor map stored internally. */ + pcl::visualization::CloudActorMapPtr actors_; + + /** \brief Collection of vtkRenderers stored internally. */ + vtkSmartPointer renderers_; +}; + +} // namespace cloud_composer + +} // namespace pcl diff --git a/apps/cloud_composer/include/pcl/apps/cloud_composer/point_selectors/selected_trackball_interactor_style.h b/apps/cloud_composer/include/pcl/apps/cloud_composer/point_selectors/selected_trackball_interactor_style.h index 3a9a20b3..9133b19e 100644 --- a/apps/cloud_composer/include/pcl/apps/cloud_composer/point_selectors/selected_trackball_interactor_style.h +++ b/apps/cloud_composer/include/pcl/apps/cloud_composer/point_selectors/selected_trackball_interactor_style.h @@ -38,85 +38,94 @@ #include #include -#include #include +#include + +namespace pcl { +namespace cloud_composer { + +class SelectedTrackballStyleInteractor : public vtkInteractorStyleTrackballActor { +public: + static SelectedTrackballStyleInteractor* + New(); + vtkTypeMacro(SelectedTrackballStyleInteractor, vtkInteractorStyleTrackballActor); + + SelectedTrackballStyleInteractor(); + + /** \brief Pass a pointer to the actor map + * \param[in] actors the actor map that will be used with this style + */ + inline void + setCloudActorMap(const pcl::visualization::CloudActorMapPtr& actors) + { + actors_ = actors; + } + + /** \brief Get the cloud actor map pointer. */ + inline pcl::visualization::CloudActorMapPtr + getCloudActorMap() const + { + return (actors_); + } -namespace pcl -{ - namespace cloud_composer + /** \brief Pass a set of renderers to the interactor style. + * \param[in] rens the vtkRendererCollection to use + */ + void + setRendererCollection(vtkSmartPointer& rens) { - - class SelectedTrackballStyleInteractor : public vtkInteractorStyleTrackballActor - { - public: - static SelectedTrackballStyleInteractor* New(); - vtkTypeMacro(SelectedTrackballStyleInteractor,vtkInteractorStyleTrackballActor); - - SelectedTrackballStyleInteractor (); - - /** \brief Pass a pointer to the actor map - * \param[in] actors the actor map that will be used with this style - */ - inline void - setCloudActorMap (const pcl::visualization::CloudActorMapPtr &actors) { actors_ = actors; } - - /** \brief Get the cloud actor map pointer. */ - inline pcl::visualization::CloudActorMapPtr - getCloudActorMap () const { return (actors_); } - - /** \brief Pass a set of renderers to the interactor style. - * \param[in] rens the vtkRendererCollection to use - */ - void - setRendererCollection (vtkSmartPointer &rens) { renderers_ = rens; } - - /** \brief Function called on left mouse button click, ie, beginning of trackball */ - void - OnLeftButtonDown () override; - - void - OnRightButtonDown () override; - - /** \brief Function called on left mouse button release, ie, end of trackball*/ - void - OnLeftButtonUp () override; - - void - OnRightButtonUp () override; - - void - Rotate() override; - void - Spin() override; - void - Pan() override; - void - UniformScale() override; - - /** \brief Event emitted once a valid selection has been made */ - int manipulation_complete_event_; - - inline void - setProjectModel (ProjectModel* model) { model_ = model; } - private: - - void - setSelectedActors (); - - /** \brief Actor map stored internally. */ - pcl::visualization::CloudActorMapPtr actors_; - - /** \brief Collection of vtkRenderers stored internally. */ - vtkSmartPointer renderers_; - - /** \brief Internal Pointer to Project Model */ - ProjectModel* model_; - - QMap > start_matrix_map_; - QMap selected_actors_map_; - - }; - + renderers_ = rens; } - -} + + /** \brief Function called on left mouse button click, ie, beginning of trackball */ + void + OnLeftButtonDown() override; + + void + OnRightButtonDown() override; + + /** \brief Function called on left mouse button release, ie, end of trackball*/ + void + OnLeftButtonUp() override; + + void + OnRightButtonUp() override; + + void + Rotate() override; + void + Spin() override; + void + Pan() override; + void + UniformScale() override; + + /** \brief Event emitted once a valid selection has been made */ + int manipulation_complete_event_; + + inline void + setProjectModel(ProjectModel* model) + { + model_ = model; + } + +private: + void + setSelectedActors(); + + /** \brief Actor map stored internally. */ + pcl::visualization::CloudActorMapPtr actors_; + + /** \brief Collection of vtkRenderers stored internally. */ + vtkSmartPointer renderers_; + + /** \brief Internal Pointer to Project Model */ + ProjectModel* model_; + + QMap> start_matrix_map_; + QMap selected_actors_map_; +}; + +} // namespace cloud_composer + +} // namespace pcl diff --git a/apps/cloud_composer/include/pcl/apps/cloud_composer/point_selectors/selection_event.h b/apps/cloud_composer/include/pcl/apps/cloud_composer/point_selectors/selection_event.h index 0e40fcb5..e32d819a 100644 --- a/apps/cloud_composer/include/pcl/apps/cloud_composer/point_selectors/selection_event.h +++ b/apps/cloud_composer/include/pcl/apps/cloud_composer/point_selectors/selection_event.h @@ -39,57 +39,68 @@ #include -#include -#include #include #include +#include #include +#include + +namespace pcl { +namespace cloud_composer { +class RectangularFrustumSelector; + +class SelectionEvent { + +public: + SelectionEvent(vtkSmartPointer selected_points, + vtkSmartPointer selected_actor, + vtkSmartPointer selected_mapper, + QMap id_selected_map, + vtkRenderer* renderer) + : selected_points_(std::move(selected_points)) + , selected_actor_(std::move(selected_actor)) + , selected_mapper_(std::move(selected_mapper)) + , id_selected_data_map_(std::move(id_selected_map)) + , renderer_(renderer) + {} + + ~SelectionEvent(); + + inline vtkIdType + getNumPoints() const + { + return selected_points_->GetNumberOfPoints(); + } -namespace pcl -{ - namespace cloud_composer + vtkSmartPointer + getPolyData() const { - class RectangularFrustumSelector; - - class SelectionEvent - { - - public: - SelectionEvent (vtkSmartPointer selected_points, vtkSmartPointer selected_actor, vtkSmartPointer selected_mapper, QMap < QString, vtkPolyData* > id_selected_map, vtkRenderer* renderer) - : selected_points_ (std::move(selected_points)) - , selected_actor_ (std::move(selected_actor)) - , selected_mapper_ (std::move(selected_mapper)) - , id_selected_data_map_ (std::move(id_selected_map)) - , renderer_ (renderer) - {} - - ~SelectionEvent (); - - inline vtkIdType - getNumPoints () const { return selected_points_->GetNumberOfPoints (); } - - vtkSmartPointer - getPolyData () const { return selected_points_; } - - vtkSmartPointer - getMapper () const { return selected_mapper_; } - - vtkSmartPointer - getActor () const { return selected_actor_; } - - void - findIndicesInItem (CloudItem* cloud_item, const pcl::PointIndices::Ptr& indices); - - private: - - vtkSmartPointer selected_points_; - vtkSmartPointer selected_actor_; - vtkSmartPointer selected_mapper_; - QMap < QString, vtkPolyData* > id_selected_data_map_; - vtkRenderer* renderer_; - - }; - + return selected_points_; } - -} + + vtkSmartPointer + getMapper() const + { + return selected_mapper_; + } + + vtkSmartPointer + getActor() const + { + return selected_actor_; + } + + void + findIndicesInItem(CloudItem* cloud_item, const pcl::PointIndices::Ptr& indices); + +private: + vtkSmartPointer selected_points_; + vtkSmartPointer selected_actor_; + vtkSmartPointer selected_mapper_; + QMap id_selected_data_map_; + vtkRenderer* renderer_; +}; + +} // namespace cloud_composer + +} // namespace pcl diff --git a/apps/cloud_composer/include/pcl/apps/cloud_composer/project_model.h b/apps/cloud_composer/include/pcl/apps/cloud_composer/project_model.h index d4b30999..5394e2f1 100644 --- a/apps/cloud_composer/include/pcl/apps/cloud_composer/project_model.h +++ b/apps/cloud_composer/include/pcl/apps/cloud_composer/project_model.h @@ -37,175 +37,179 @@ #pragma once -#include -#include - -#include - #include -#include -#include #include +#include +#include +#include #include +#include +#include + class QItemSelection; class QItemSelectionModel; -namespace pcl -{ - namespace cloud_composer +namespace pcl { +namespace cloud_composer { +class CloudCommand; +class AbstractTool; +class WorkQueue; +class CloudComposerItem; +class CloudView; +class InteractorStyleSwitch; + +class ProjectModel : public QStandardItemModel { + Q_OBJECT + +public: + ProjectModel(QObject* parent = nullptr); + ProjectModel(const ProjectModel& to_copy); + ~ProjectModel(); + + ProjectModel(QString project_name, QObject* parent = nullptr); + + inline const QString + getName() + { + return horizontalHeaderItem(0)->text(); + } + + inline QUndoStack* + getUndoStack() { - class CloudCommand; - class AbstractTool; - class WorkQueue; - class CloudComposerItem; - class CloudView; - class InteractorStyleSwitch; - - class ProjectModel : public QStandardItemModel - { - Q_OBJECT - - public: - ProjectModel (QObject *parent = nullptr); - ProjectModel (const ProjectModel& to_copy); - ~ProjectModel (); - - ProjectModel (QString project_name, QObject *parent = nullptr); - - inline const QString - getName () { return horizontalHeaderItem (0)->text (); } - - inline QUndoStack* - getUndoStack () { return undo_stack_; } - - /** \brief Sets the name of the project using the horizontalHeaderItem */ - void - setName (const QString& new_name); - - /** \brief Returns the selection model which is used for this project */ - inline QItemSelectionModel* - getSelectionModel () - { - return selection_model_; - } - - - - /** \brief Takes tool object issues signal to work queue to take control of it */ - void - enqueueToolAction (AbstractTool* tool); - - /** \brief Helper function which inserts the item into this model and makes connections for properties */ - void - insertNewCloudComposerItem (CloudComposerItem* new_item, QStandardItem* parent_item); - - /** \brief Sets the CloudView that this project is rendering in */ - void - setCloudView (CloudView* view); - - /** \brief This sets the selection for points which have been selected in the QVTKWindow */ - void - setPointSelection (const std::shared_ptr& selected_event); - - /** \brief This is invoked to perform the manipulations specified on the model */ - void - manipulateClouds (const std::shared_ptr& manip_event); - public Q_SLOTS: - void - commandCompleted (CloudCommand* command); - - void - clearSelection (); - - void - deleteSelectedItems (); - - /** \brief Loads from file and inserts a new pointcloud into the model */ - void - insertNewCloudFromFile (); - - /** \brief Loads from rgb and depth file and inserts a new pointcloud into the model */ - void - insertNewCloudFromRGBandDepth (); - - /** \brief Opens a file dialog and saves selected cloud to file */ - void - saveSelectedCloudToFile (); - - /** \brief This emits all the state signals, which updates the GUI action button status (enabled/disabled)" */ - void - emitAllStateSignals (); - - /** \brief This sets whether the CloudView for this project shows axes */ - void - setAxisVisibility (bool visible); - - /** \brief Slot called when the mouse style selected in the GUI changes */ - void - mouseStyleChanged (QAction* new_style_action); - - /** \brief Slot Called whenever the item selection_model_ changes */ - void - itemSelectionChanged ( const QItemSelection &, const QItemSelection &); - - /** \brief Creates a new cloud from the selected items and points */ - void - createNewCloudFromSelection (); - - /** \brief Selects all items in the model */ - void - selectAllItems (QStandardItem* item = nullptr ); - Q_SIGNALS: - void - enqueueNewAction (AbstractTool* tool, ConstItemList data); - - /** \brief Catch-all signal emitted whenever the model changes */ - void - modelChanged (); - - void - axisVisible (const bool axis_visible); - - void - deleteAvailable (bool can_delete); - - void - newCloudFromSelectionAvailable (bool can_create); - - void - mouseStyleState (interactor_styles::INTERACTOR_STYLES); - - private: - /** \brief Checks to see if selection contains only CloudItem s */ - bool - onlyCloudItemsSelected (); - - QItemSelectionModel* selection_model_; - QMap name_to_type_map_; - QUndoStack* undo_stack_; - WorkQueue* work_queue_; - QThread* work_thread_; - CloudView* cloud_view_; - - /** \brief Stores last directory used in file read/write operations */ - QDir last_directory_; - - //Variables for toggle action status - bool axis_visible_; - QMap selected_style_map_; - /** \brief Internal helper function for updating map */ - void - setSelectedStyle (interactor_styles::INTERACTOR_STYLES style); - - /** \brief Internal pointer storing the last selection event arriving from vtk */ - std::shared_ptr selection_event_; - /** \brief Map which stores which cloud items and indices were selected in the selection_event_ */ - QMap selected_item_index_map_; - }; + return undo_stack_; } -} -Q_DECLARE_METATYPE (pcl::cloud_composer::ProjectModel); -Q_DECLARE_METATYPE (pcl::cloud_composer::interactor_styles::INTERACTOR_STYLES); + /** \brief Sets the name of the project using the horizontalHeaderItem */ + void + setName(const QString& new_name); + + /** \brief Returns the selection model which is used for this project */ + inline QItemSelectionModel* + getSelectionModel() + { + return selection_model_; + } + + /** \brief Takes tool object issues signal to work queue to take control of it */ + void + enqueueToolAction(AbstractTool* tool); + + /** \brief Helper function which inserts the item into this model and makes + * connections for properties */ + void + insertNewCloudComposerItem(CloudComposerItem* new_item, QStandardItem* parent_item); + + /** \brief Sets the CloudView that this project is rendering in */ + void + setCloudView(CloudView* view); + + /** \brief This sets the selection for points which have been selected in the + * QVTKWindow */ + void + setPointSelection(const std::shared_ptr& selected_event); + + /** \brief This is invoked to perform the manipulations specified on the model */ + void + manipulateClouds(const std::shared_ptr& manip_event); +public Q_SLOTS: + void + commandCompleted(CloudCommand* command); + + void + clearSelection(); + + void + deleteSelectedItems(); + + /** \brief Loads from file and inserts a new pointcloud into the model */ + void + insertNewCloudFromFile(); + + /** \brief Loads from rgb and depth file and inserts a new pointcloud into the model + */ + void + insertNewCloudFromRGBandDepth(); + + /** \brief Opens a file dialog and saves selected cloud to file */ + void + saveSelectedCloudToFile(); + + /** \brief This emits all the state signals, which updates the GUI action button + * status (enabled/disabled)" */ + void + emitAllStateSignals(); + + /** \brief This sets whether the CloudView for this project shows axes */ + void + setAxisVisibility(bool visible); + + /** \brief Slot called when the mouse style selected in the GUI changes */ + void + mouseStyleChanged(QAction* new_style_action); + + /** \brief Slot Called whenever the item selection_model_ changes */ + void + itemSelectionChanged(const QItemSelection&, const QItemSelection&); + + /** \brief Creates a new cloud from the selected items and points */ + void + createNewCloudFromSelection(); + + /** \brief Selects all items in the model */ + void + selectAllItems(QStandardItem* item = nullptr); +Q_SIGNALS: + void + enqueueNewAction(AbstractTool* tool, ConstItemList data); + + /** \brief Catch-all signal emitted whenever the model changes */ + void + modelChanged(); + + void + axisVisible(const bool axis_visible); + + void + deleteAvailable(bool can_delete); + + void + newCloudFromSelectionAvailable(bool can_create); + + void mouseStyleState(interactor_styles::INTERACTOR_STYLES); + +private: + /** \brief Checks to see if selection contains only CloudItem s */ + bool + onlyCloudItemsSelected(); + + QItemSelectionModel* selection_model_; + QMap name_to_type_map_; + QUndoStack* undo_stack_; + WorkQueue* work_queue_; + QThread* work_thread_; + CloudView* cloud_view_; + + /** \brief Stores last directory used in file read/write operations */ + QDir last_directory_; + + // Variables for toggle action status + bool axis_visible_; + QMap selected_style_map_; + /** \brief Internal helper function for updating map */ + void + setSelectedStyle(interactor_styles::INTERACTOR_STYLES style); + + /** \brief Internal pointer storing the last selection event arriving from vtk */ + std::shared_ptr selection_event_; + /** \brief Map which stores which cloud items and indices were selected in the + * selection_event_ */ + QMap selected_item_index_map_; +}; +} // namespace cloud_composer +} // namespace pcl + +Q_DECLARE_METATYPE(pcl::cloud_composer::ProjectModel); +Q_DECLARE_METATYPE(pcl::cloud_composer::interactor_styles::INTERACTOR_STYLES); diff --git a/apps/cloud_composer/include/pcl/apps/cloud_composer/properties_model.h b/apps/cloud_composer/include/pcl/apps/cloud_composer/properties_model.h index 57460d14..a4747ca4 100644 --- a/apps/cloud_composer/include/pcl/apps/cloud_composer/properties_model.h +++ b/apps/cloud_composer/include/pcl/apps/cloud_composer/properties_model.h @@ -39,52 +39,50 @@ #include -namespace pcl -{ - namespace cloud_composer - { - class CloudComposerItem; - class PropertiesModel : public QStandardItemModel - { - Q_OBJECT - public: - - /** \brief Constructor used for tool parameters */ - PropertiesModel (QObject *parent = nullptr); - /** \brief Constructor used for item parameters */ - PropertiesModel (CloudComposerItem* parent_item, QObject *parent = nullptr); - PropertiesModel (const PropertiesModel& to_copy); - - /** \brief Helper function for adding a new property */ - void - addProperty (const QString& prop_name, const QVariant& value, const Qt::ItemFlags flags = Qt::ItemIsSelectable, const QString& category = ""); - - /** \brief Helper function for adding a new property category */ - void - addCategory (const QString& category_name); - - /** \brief Helper function to get a property */ - QVariant - getProperty (const QString& prop_name) const; - - void - copyProperties (const PropertiesModel* to_copy); - - public Q_SLOTS: - void - propertyChanged (QStandardItem* property_item); - - Q_SIGNALS: - void - propertyChanged (const QStandardItem* property_item, const CloudComposerItem* parent_item_); - - - private: - CloudComposerItem* parent_item_; - - }; - } -} +namespace pcl { +namespace cloud_composer { +class CloudComposerItem; +class PropertiesModel : public QStandardItemModel { + Q_OBJECT +public: + /** \brief Constructor used for tool parameters */ + PropertiesModel(QObject* parent = nullptr); + /** \brief Constructor used for item parameters */ + PropertiesModel(CloudComposerItem* parent_item, QObject* parent = nullptr); + PropertiesModel(const PropertiesModel& to_copy); -Q_DECLARE_METATYPE (pcl::cloud_composer::PropertiesModel); -Q_DECLARE_METATYPE (pcl::cloud_composer::PropertiesModel*); + /** \brief Helper function for adding a new property */ + void + addProperty(const QString& prop_name, + const QVariant& value, + const Qt::ItemFlags flags = Qt::ItemIsSelectable, + const QString& category = ""); + + /** \brief Helper function for adding a new property category */ + void + addCategory(const QString& category_name); + + /** \brief Helper function to get a property */ + QVariant + getProperty(const QString& prop_name) const; + + void + copyProperties(const PropertiesModel* to_copy); + +public Q_SLOTS: + void + propertyChanged(QStandardItem* property_item); + +Q_SIGNALS: + void + propertyChanged(const QStandardItem* property_item, + const CloudComposerItem* parent_item_); + +private: + CloudComposerItem* parent_item_; +}; +} // namespace cloud_composer +} // namespace pcl + +Q_DECLARE_METATYPE(pcl::cloud_composer::PropertiesModel); +Q_DECLARE_METATYPE(pcl::cloud_composer::PropertiesModel*); diff --git a/apps/cloud_composer/include/pcl/apps/cloud_composer/signal_multiplexer.h b/apps/cloud_composer/include/pcl/apps/cloud_composer/signal_multiplexer.h index c8a5224f..4e27838b 100644 --- a/apps/cloud_composer/include/pcl/apps/cloud_composer/signal_multiplexer.h +++ b/apps/cloud_composer/include/pcl/apps/cloud_composer/signal_multiplexer.h @@ -1,12 +1,12 @@ /* * Software License Agreement (BSD License) * - * + * * Class to multiplex signal and slot connections. Qt 3 code from: * http://doc.trolltech.com/qq/qq08-action-multiplexer.html. * Converted to Qt 4 by a.somers@rathenau.nl. - * Modified for use in cloud_composer by jpapon@gmail.com - * + * Modified for use in cloud_composer by jpapon@gmail.com + * * Point Cloud Library (PCL) - www.pointclouds.org * * All rights reserved. @@ -46,106 +46,105 @@ #include #include -namespace pcl -{ - namespace cloud_composer +namespace pcl { +namespace cloud_composer { +class SignalMultiplexer : public QObject { + Q_OBJECT + +public: + SignalMultiplexer(QObject* parent = nullptr); + + /** + Use this connect function instead of QObject::connect() to connect + an actions activation signal to the receiving, multiplexed object. + + @param sender the sending action or object + @param signal the signal in the sender object that is connected to + @param slot the slot in the receiving object that is set through @ref + setCurrentObject that the signal should be connected to. + + @see connect(const char *signal, QObject *receiver, const char *slot) + @see disconnect(QObject *sender, const char *signal, const char *slot) + */ + void + connect(QObject* sender, const char* signal, const char* slot); + + /** + Disconnects a signal connection from a sending object to a multiplexed + receiving object. + @see connect(const char *signal, QObject *receiver, const char *slot) + */ + bool + disconnect(QObject* sender, const char* signal, const char* slot); + + /** + Use this connect function instead of QObject::connect() to connect + a multiplexed object's (status) signal to an action object's slot. + + @param signal the signal in the multiplexed sender object that is set through + @ref setCurrentObject that the connection should be from + @param receiver the receiving action or object + @param slot the slot in the receiving object + + @see connect(QObject *sender, const char *signal, const char *slot) + @see disconnect(const char *signal, QObject *receiver, const char *slot) + */ + void + connect(const char* signal, QObject* receiver, const char* slot); + + /** + Disconnects a signal from a multiplexed object to a receiving (action) + object. + @see connect(const char *signal, QObject *receiver, const char *slot) + */ + bool + disconnect(const char* signal, QObject* receiver, const char* slot); + + /** + @returns the object the connections are currently made with. + */ + QObject* + currentObject() const { - class SignalMultiplexer : public QObject - { - Q_OBJECT - - public: - SignalMultiplexer(QObject *parent = nullptr); - - /** - Use this connect function instead of QObject::connect() to connect - an actions activation signal to the receiving, multiplexed object. - - @param sender the sending action or object - @param signal the signal in the sender object that is connected to - @param slot the slot in the receiving object that is set through @ref - setCurrentObject that the signal should be connected to. - - @see connect(const char *signal, QObject *receiver, const char *slot) - @see disconnect(QObject *sender, const char *signal, const char *slot) - */ - void - connect (QObject *sender, const char *signal, const char *slot); - - /** - Disconnects a signal connection from a sending object to a multiplexed - receiving object. - @see connect(const char *signal, QObject *receiver, const char *slot) - */ - bool - disconnect (QObject *sender, const char *signal, const char *slot); - - /** - Use this connect function instead of QObject::connect() to connect - a multiplexed object's (status) signal to an action object's slot. - - @param signal the signal in the multiplexed sender object that is set through - @ref setCurrentObject that the connection should be from - @param receiver the receiving action or object - @param slot the slot in the receiving object - - @see connect(QObject *sender, const char *signal, const char *slot) - @see disconnect(const char *signal, QObject *receiver, const char *slot) - */ - void - connect (const char *signal, QObject *receiver, const char *slot); - - /** - Disconnects a signal from a multiplexed object to a receiving (action) - object. - @see connect(const char *signal, QObject *receiver, const char *slot) - */ - bool - disconnect (const char *signal, QObject *receiver, const char *slot); - - /** - @returns the object the connections are currently made with. - */ - QObject - *currentObject () const { return object; } - - public Q_SLOTS: - /** - Sets the current object the signals that are managed by the - SignalMultiplexer instance should be connected to. Any connections - of these signals to the previous object will be disconnected. - After the connections are hooked to the new object, the - @ref currentObjectChanged signal will be emitted. - - @param newObject the new object that the signals should be connected to - */ - void - setCurrentObject (QObject *newObject); - - Q_SIGNALS: - /** - Emitted when a new object is set to receive the signals managed by - this SignalMultiplexer instance. - */ - void - currentObjectChanged (QObject* newObject); - - private: - struct Connection - { - QPointer sender; - QPointer receiver; - const char *signal; - const char *slot; - }; - - void - connect (const Connection &conn); - void - disconnect (const Connection &conn); - - QPointer object; - QList connections; - }; + return object; } -} + +public Q_SLOTS: + /** + Sets the current object the signals that are managed by the + SignalMultiplexer instance should be connected to. Any connections + of these signals to the previous object will be disconnected. + After the connections are hooked to the new object, the + @ref currentObjectChanged signal will be emitted. + + @param newObject the new object that the signals should be connected to + */ + void + setCurrentObject(QObject* newObject); + +Q_SIGNALS: + /** + Emitted when a new object is set to receive the signals managed by + this SignalMultiplexer instance. + */ + void + currentObjectChanged(QObject* newObject); + +private: + struct Connection { + QPointer sender; + QPointer receiver; + const char* signal; + const char* slot; + }; + + void + connect(const Connection& conn); + void + disconnect(const Connection& conn); + + QPointer object; + QList connections; +}; +} // namespace cloud_composer +} // namespace pcl diff --git a/apps/cloud_composer/include/pcl/apps/cloud_composer/tool_interface/abstract_tool.h b/apps/cloud_composer/include/pcl/apps/cloud_composer/tool_interface/abstract_tool.h index 1eb18eaf..30bd0608 100644 --- a/apps/cloud_composer/include/pcl/apps/cloud_composer/tool_interface/abstract_tool.h +++ b/apps/cloud_composer/include/pcl/apps/cloud_composer/tool_interface/abstract_tool.h @@ -43,137 +43,145 @@ #include -namespace pcl -{ - namespace cloud_composer +namespace pcl { +namespace cloud_composer { + +class AbstractTool : public QObject { + Q_OBJECT +public: + AbstractTool(PropertiesModel* parameter_model, QObject* parent); + + ~AbstractTool() { qDebug() << "Tool Destructed"; } + + /** \brief Function called which does work in plugin + * \param data input_data from the model - const for good reason + * Returned list will become the output, replacing input_data in the model - you must + * deep copy the input_data, since undo works by switching back and forth + */ + virtual QList + performAction(QList input_data, + PointTypeFlags::PointType type = PointTypeFlags::NONE) = 0; + + virtual CloudCommand* + createCommand(QList input_data) = 0; + + QString + getActionText() const + { + return action_text_; + } + + void + setActionText(const QString& text) + { + action_text_ = text; + } + + virtual QString + getToolName() const = 0; + +protected: + PropertiesModel* parameter_model_; + +private: + QString action_text_; +}; + +class ModifyItemTool : public AbstractTool { + Q_OBJECT +public: + ModifyItemTool(PropertiesModel* parameter_model, QObject* parent) + : AbstractTool(parameter_model, parent) + {} + + QList + performAction(QList input_data, + PointTypeFlags::PointType type = PointTypeFlags::NONE) override = 0; + + inline CloudCommand* + createCommand(QList input_data) override { - - - class AbstractTool : public QObject - { - Q_OBJECT - public: - - AbstractTool (PropertiesModel* parameter_model, QObject* parent); - - ~AbstractTool () { qDebug() << "Tool Destructed"; } - - /** \brief Function called which does work in plugin - * \param data input_data from the model - const for good reason - * Returned list will become the output, replacing input_data in the model - you must deep copy - * the input_data, since undo works by switching back and forth - */ - virtual QList - performAction (QList input_data, PointTypeFlags::PointType type = PointTypeFlags::NONE) = 0; - - virtual CloudCommand* - createCommand (QList input_data) = 0; - - QString - getActionText () const {return action_text_;} - - void - setActionText (const QString& text) { action_text_ = text; } - - virtual QString - getToolName () const = 0; - - protected: - - PropertiesModel* parameter_model_; - - private: - QString action_text_; - - }; - - class ModifyItemTool : public AbstractTool - { - Q_OBJECT - public: - ModifyItemTool (PropertiesModel* parameter_model, QObject* parent) - : AbstractTool (parameter_model, parent) - {} - - QList - performAction (QList input_data, PointTypeFlags::PointType type = PointTypeFlags::NONE) override = 0; - - inline CloudCommand* - createCommand (QList input_data) override - { - return new ModifyItemCommand (input_data); - } - - inline QString - getToolName () const override { return "ModifyItemTool";} - - }; - - class NewItemTool : public AbstractTool - { - Q_OBJECT - public: - NewItemTool (PropertiesModel* parameter_model, QObject* parent) - : AbstractTool (parameter_model, parent) - {} - - QList - performAction (QList input_data, PointTypeFlags::PointType type = PointTypeFlags::NONE) override = 0; - - inline CloudCommand* - createCommand (QList input_data) override - { - return new NewItemCloudCommand (input_data); - } - - inline QString - getToolName () const override { return "NewItemTool";} - - }; - - class SplitItemTool : public AbstractTool - { - Q_OBJECT - public: - SplitItemTool (PropertiesModel* parameter_model, QObject* parent) - : AbstractTool (parameter_model, parent) - {} - - QList - performAction (QList input_data, PointTypeFlags::PointType type = PointTypeFlags::NONE) override = 0; - - inline CloudCommand* - createCommand (QList input_data) override - { - return new SplitCloudCommand (input_data); - } - - inline QString - getToolName () const override { return "SplitItemTool";} - - }; - - class MergeCloudTool : public AbstractTool - { - Q_OBJECT - public: - MergeCloudTool (PropertiesModel* parameter_model, QObject* parent) - : AbstractTool (parameter_model, parent) - {} - - QList - performAction (QList input_data, PointTypeFlags::PointType type = PointTypeFlags::NONE) override = 0; - - inline CloudCommand* - createCommand (QList input_data) override - { - return new MergeCloudCommand (input_data); - } - - inline QString - getToolName () const override { return "MergeCloudTool";} - - }; + return new ModifyItemCommand(input_data); + } + inline QString + getToolName() const override + { + return "ModifyItemTool"; } -} +}; + +class NewItemTool : public AbstractTool { + Q_OBJECT +public: + NewItemTool(PropertiesModel* parameter_model, QObject* parent) + : AbstractTool(parameter_model, parent) + {} + + QList + performAction(QList input_data, + PointTypeFlags::PointType type = PointTypeFlags::NONE) override = 0; + + inline CloudCommand* + createCommand(QList input_data) override + { + return new NewItemCloudCommand(input_data); + } + + inline QString + getToolName() const override + { + return "NewItemTool"; + } +}; + +class SplitItemTool : public AbstractTool { + Q_OBJECT +public: + SplitItemTool(PropertiesModel* parameter_model, QObject* parent) + : AbstractTool(parameter_model, parent) + {} + + QList + performAction(QList input_data, + PointTypeFlags::PointType type = PointTypeFlags::NONE) override = 0; + + inline CloudCommand* + createCommand(QList input_data) override + { + return new SplitCloudCommand(input_data); + } + + inline QString + getToolName() const override + { + return "SplitItemTool"; + } +}; + +class MergeCloudTool : public AbstractTool { + Q_OBJECT +public: + MergeCloudTool(PropertiesModel* parameter_model, QObject* parent) + : AbstractTool(parameter_model, parent) + {} + + QList + performAction(QList input_data, + PointTypeFlags::PointType type = PointTypeFlags::NONE) override = 0; + + inline CloudCommand* + createCommand(QList input_data) override + { + return new MergeCloudCommand(input_data); + } + + inline QString + getToolName() const override + { + return "MergeCloudTool"; + } +}; + +} // namespace cloud_composer +} // namespace pcl diff --git a/apps/cloud_composer/include/pcl/apps/cloud_composer/tool_interface/tool_factory.h b/apps/cloud_composer/include/pcl/apps/cloud_composer/tool_interface/tool_factory.h index 65781efa..a8a7a242 100644 --- a/apps/cloud_composer/include/pcl/apps/cloud_composer/tool_interface/tool_factory.h +++ b/apps/cloud_composer/include/pcl/apps/cloud_composer/tool_interface/tool_factory.h @@ -41,55 +41,52 @@ class QAction; -namespace pcl -{ - namespace cloud_composer - { - - - class AbstractTool; - class AbstractCommand; - class PropertiesModel; - - class ToolFactory - { - public: - virtual AbstractTool* - createTool (PropertiesModel* parameter_model = nullptr, QObject* parent = nullptr) = 0; - - virtual PropertiesModel* - createToolParameterModel (QObject* parent) = 0; - - virtual QString - getPluginName () const = 0; - - virtual QString - getToolGroupName () const = 0; - - virtual QString - getIconName () const = 0; - - /** \brief Reimplement this function to return the proper number if tool requires more than one input item */ - inline virtual int - getNumInputItems () const - { - return 1; - } - - /** \brief Returns a list of allowed input item types. Implement in tools so GUI can prevent impossible actions */ - virtual CloudComposerItem::ItemType - getInputItemType () const = 0; - - /** \brief Returns a list of required input children. Implement in tools so GUI can prevent impossible actions */ - virtual QList - getRequiredInputChildrenTypes () const = 0; - - }; +namespace pcl { +namespace cloud_composer { + +class AbstractTool; +class AbstractCommand; +class PropertiesModel; + +class ToolFactory { +public: + virtual AbstractTool* + createTool(PropertiesModel* parameter_model = nullptr, QObject* parent = nullptr) = 0; + + virtual PropertiesModel* + createToolParameterModel(QObject* parent) = 0; + + virtual QString + getPluginName() const = 0; + + virtual QString + getToolGroupName() const = 0; + virtual QString + getIconName() const = 0; + + /** \brief Reimplement this function to return the proper number if tool requires more + * than one input item */ + inline virtual int + getNumInputItems() const + { + return 1; } -} -Q_DECLARE_METATYPE (pcl::cloud_composer::ToolFactory*); + /** \brief Returns a list of allowed input item types. Implement in tools so GUI can + * prevent impossible actions */ + virtual CloudComposerItem::ItemType + getInputItemType() const = 0; + + /** \brief Returns a list of required input children. Implement in tools so GUI can + * prevent impossible actions */ + virtual QList + getRequiredInputChildrenTypes() const = 0; +}; + +} // namespace cloud_composer +} // namespace pcl + +Q_DECLARE_METATYPE(pcl::cloud_composer::ToolFactory*); -Q_DECLARE_INTERFACE(pcl::cloud_composer::ToolFactory, - "cloud_composer.ToolFactory/1.0") +Q_DECLARE_INTERFACE(pcl::cloud_composer::ToolFactory, "cloud_composer.ToolFactory/1.0") diff --git a/apps/cloud_composer/include/pcl/apps/cloud_composer/toolbox_model.h b/apps/cloud_composer/include/pcl/apps/cloud_composer/toolbox_model.h index 0121b56b..f109c8d9 100644 --- a/apps/cloud_composer/include/pcl/apps/cloud_composer/toolbox_model.h +++ b/apps/cloud_composer/include/pcl/apps/cloud_composer/toolbox_model.h @@ -44,8 +44,7 @@ class QItemSelection; class QItemSelectionModel; class QTreeView; -enum TOOLBOX_ROLES -{ +enum TOOLBOX_ROLES { FACTORY = Qt::UserRole, PARAMETER_MODEL, ALLOWED_INPUT_ITEM_TYPES, @@ -53,71 +52,72 @@ enum TOOLBOX_ROLES }; class QTreeView; -namespace pcl -{ - namespace cloud_composer - { - - class CloudCommand; - class AbstractTool; - class ToolFactory; - class ProjectModel; - - class ToolBoxModel : public QStandardItemModel - { - Q_OBJECT - - public: - ToolBoxModel (QTreeView* tool_view = nullptr, QTreeView* parameter_view = nullptr, QObject *parent = nullptr); - ToolBoxModel (const ToolBoxModel& to_copy); - - void - addTool (ToolFactory* tool_factory); - - void - setSelectionModel (QItemSelectionModel* selection_model); - - /** \brief Enables/Disables Tools based on currently selected items from model */ - void - updateEnabledTools (const QItemSelection& current_selection); - - void - enableAllTools (); - - public Q_SLOTS: - void - activeProjectChanged (ProjectModel* new_model, ProjectModel* previous_model); - - void - selectedToolChanged (const QModelIndex & current, const QModelIndex & previous); - - void - toolAction (); - - /** \brief This slot is called when the selection in cloud browser changes. Updates enabling of tools */ - void - selectedItemChanged ( const QItemSelection & selected, const QItemSelection & deselected ); - - /** \brief This slot is called whenever the current project model emits layoutChanged, and calls updateEnabledTools */ - void - modelChanged (); - Q_SIGNALS: - void - enqueueToolAction (AbstractTool* tool); - - private: - QStandardItem* - addToolGroup (const QString& tool_group_name); - - QTreeView* tool_view_; - QTreeView* parameter_view_; - QItemSelectionModel* selection_model_; - QSet tool_items; - - ProjectModel* project_model_; - }; - } -} - -Q_DECLARE_METATYPE (pcl::cloud_composer::ToolBoxModel); -Q_DECLARE_METATYPE (QStandardItemModel*); +namespace pcl { +namespace cloud_composer { + +class CloudCommand; +class AbstractTool; +class ToolFactory; +class ProjectModel; + +class ToolBoxModel : public QStandardItemModel { + Q_OBJECT + +public: + ToolBoxModel(QTreeView* tool_view = nullptr, + QTreeView* parameter_view = nullptr, + QObject* parent = nullptr); + ToolBoxModel(const ToolBoxModel& to_copy); + + void + addTool(ToolFactory* tool_factory); + + void + setSelectionModel(QItemSelectionModel* selection_model); + + /** \brief Enables/Disables Tools based on currently selected items from model */ + void + updateEnabledTools(const QItemSelection& current_selection); + + void + enableAllTools(); + +public Q_SLOTS: + void + activeProjectChanged(ProjectModel* new_model, ProjectModel* previous_model); + + void + selectedToolChanged(const QModelIndex& current, const QModelIndex& previous); + + void + toolAction(); + + /** \brief This slot is called when the selection in cloud browser changes. Updates + * enabling of tools */ + void + selectedItemChanged(const QItemSelection& selected, const QItemSelection& deselected); + + /** \brief This slot is called whenever the current project model emits layoutChanged, + * and calls updateEnabledTools */ + void + modelChanged(); +Q_SIGNALS: + void + enqueueToolAction(AbstractTool* tool); + +private: + QStandardItem* + addToolGroup(const QString& tool_group_name); + + QTreeView* tool_view_; + QTreeView* parameter_view_; + QItemSelectionModel* selection_model_; + QSet tool_items; + + ProjectModel* project_model_; +}; +} // namespace cloud_composer +} // namespace pcl + +Q_DECLARE_METATYPE(pcl::cloud_composer::ToolBoxModel); +Q_DECLARE_METATYPE(QStandardItemModel*); diff --git a/apps/cloud_composer/include/pcl/apps/cloud_composer/tools/euclidean_clustering.h b/apps/cloud_composer/include/pcl/apps/cloud_composer/tools/euclidean_clustering.h index 9a9e82d7..c97be097 100644 --- a/apps/cloud_composer/include/pcl/apps/cloud_composer/tools/euclidean_clustering.h +++ b/apps/cloud_composer/include/pcl/apps/cloud_composer/tools/euclidean_clustering.h @@ -40,62 +40,68 @@ #include #include -namespace pcl -{ - namespace cloud_composer +namespace pcl { +namespace cloud_composer { +class EuclideanClusteringTool : public SplitItemTool { + Q_OBJECT +public: + EuclideanClusteringTool(PropertiesModel* parameter_model, QObject* parent); + + QList + performAction(QList input_data, + PointTypeFlags::PointType type = PointTypeFlags::NONE) override; + + inline QString + getToolName() const override + { + return "Euclidean Clustering Tool"; + } +}; + +class EuclideanClusteringToolFactory : public QObject, public ToolFactory { + Q_OBJECT + Q_INTERFACES(pcl::cloud_composer::ToolFactory) + Q_PLUGIN_METADATA(IID "cloud_composer.ToolFactory/1.0") +public: + SplitItemTool* + createTool(PropertiesModel* parameter_model, QObject* parent = nullptr) override + { + return new EuclideanClusteringTool(parameter_model, parent); + } + + PropertiesModel* + createToolParameterModel(QObject* parent) override; + + inline QString + getPluginName() const override { - class EuclideanClusteringTool : public SplitItemTool - { - Q_OBJECT - public: - EuclideanClusteringTool (PropertiesModel* parameter_model, QObject* parent); - - QList - performAction (QList input_data, PointTypeFlags::PointType type = PointTypeFlags::NONE) override; - - inline QString - getToolName () const override { return "Euclidean Clustering Tool";} - }; + return "Euclidean Clustering"; + } - - class EuclideanClusteringToolFactory : public QObject, public ToolFactory - { - Q_OBJECT - Q_INTERFACES (pcl::cloud_composer::ToolFactory) - Q_PLUGIN_METADATA(IID "cloud_composer.ToolFactory/1.0") - public: - SplitItemTool* - createTool (PropertiesModel* parameter_model, QObject* parent = nullptr) override - { - return new EuclideanClusteringTool(parameter_model, parent); - } - - PropertiesModel* - createToolParameterModel (QObject* parent) override; - - inline QString - getPluginName () const override { return "Euclidean Clustering";} - - inline QString - getToolGroupName () const override { return "Segmentation";} - - inline QString - getIconName () const override { return ":/euclidean_clustering.png"; } - - inline CloudComposerItem::ItemType - getInputItemType () const override - { - return CloudComposerItem::CLOUD_ITEM; - } - - inline QList - getRequiredInputChildrenTypes () const override - { - return QList (); - } - }; + inline QString + getToolGroupName() const override + { + return "Segmentation"; + } + inline QString + getIconName() const override + { + return ":/euclidean_clustering.png"; + } + inline CloudComposerItem::ItemType + getInputItemType() const override + { + return CloudComposerItem::CLOUD_ITEM; + } + inline QList + getRequiredInputChildrenTypes() const override + { + return QList(); } -} +}; + +} // namespace cloud_composer +} // namespace pcl diff --git a/apps/cloud_composer/include/pcl/apps/cloud_composer/tools/fpfh_estimation.h b/apps/cloud_composer/include/pcl/apps/cloud_composer/tools/fpfh_estimation.h index 10287e4c..35210217 100644 --- a/apps/cloud_composer/include/pcl/apps/cloud_composer/tools/fpfh_estimation.h +++ b/apps/cloud_composer/include/pcl/apps/cloud_composer/tools/fpfh_estimation.h @@ -40,64 +40,70 @@ #include #include -namespace pcl -{ - namespace cloud_composer +namespace pcl { +namespace cloud_composer { + +class FPFHEstimationTool : public NewItemTool { + Q_OBJECT +public: + FPFHEstimationTool(PropertiesModel* parameter_model, QObject* parent); + + QList + performAction(QList input_data, + PointTypeFlags::PointType type = PointTypeFlags::NONE) override; + + inline QString + getToolName() const override { - - class FPFHEstimationTool : public NewItemTool - { - Q_OBJECT - public: - FPFHEstimationTool (PropertiesModel* parameter_model, QObject* parent); - - QList - performAction (QList input_data, PointTypeFlags::PointType type = PointTypeFlags::NONE) override; - - inline QString - getToolName () const override { return "FPFH Estimation Tool";} - }; + return "FPFH Estimation Tool"; + } +}; - - class FPFHEstimationToolFactory : public QObject, public ToolFactory - { - Q_OBJECT - Q_INTERFACES (pcl::cloud_composer::ToolFactory) - Q_PLUGIN_METADATA(IID "cloud_composer.ToolFactory/1.0") - public: - NewItemTool* - createTool (PropertiesModel* parameter_model, QObject* parent = nullptr) override - { - return new FPFHEstimationTool(parameter_model, parent); - } - - PropertiesModel* - createToolParameterModel (QObject* parent) override; - - inline QString - getPluginName () const override { return "FPFH Estimation";} - - QString - getToolGroupName () const override { return "Feature Estimation";} - - QString - getIconName () const override { return ":/fpfh_estimation.png"; } - - inline CloudComposerItem::ItemType - getInputItemType () const override - { - return CloudComposerItem::CLOUD_ITEM; - } - - inline QList - getRequiredInputChildrenTypes () const override - { - QList input_types; - return (input_types << CloudComposerItem::NORMALS_ITEM); - } - }; +class FPFHEstimationToolFactory : public QObject, public ToolFactory { + Q_OBJECT + Q_INTERFACES(pcl::cloud_composer::ToolFactory) + Q_PLUGIN_METADATA(IID "cloud_composer.ToolFactory/1.0") +public: + NewItemTool* + createTool(PropertiesModel* parameter_model, QObject* parent = nullptr) override + { + return new FPFHEstimationTool(parameter_model, parent); + } + PropertiesModel* + createToolParameterModel(QObject* parent) override; + inline QString + getPluginName() const override + { + return "FPFH Estimation"; + } + QString + getToolGroupName() const override + { + return "Feature Estimation"; } -} + + QString + getIconName() const override + { + return ":/fpfh_estimation.png"; + } + + inline CloudComposerItem::ItemType + getInputItemType() const override + { + return CloudComposerItem::CLOUD_ITEM; + } + + inline QList + getRequiredInputChildrenTypes() const override + { + QList input_types; + return (input_types << CloudComposerItem::NORMALS_ITEM); + } +}; + +} // namespace cloud_composer +} // namespace pcl diff --git a/apps/cloud_composer/include/pcl/apps/cloud_composer/tools/impl/organized_segmentation.hpp b/apps/cloud_composer/include/pcl/apps/cloud_composer/tools/impl/organized_segmentation.hpp index 708ea1f3..a200e83c 100644 --- a/apps/cloud_composer/include/pcl/apps/cloud_composer/tools/impl/organized_segmentation.hpp +++ b/apps/cloud_composer/include/pcl/apps/cloud_composer/tools/impl/organized_segmentation.hpp @@ -38,144 +38,160 @@ #ifndef IMPL_ORGANIZED_SEGMENTATION_HPP_ #define IMPL_ORGANIZED_SEGMENTATION_HPP_ -#include #include #include -#include // for pcl::make_shared -#include - -#include -#include -#include -#include +#include +#include #include #include +#include #include +#include +#include +#include +#include // for pcl::make_shared +#include - -template QList -pcl::cloud_composer::OrganizedSegmentationTool::performTemplatedAction (const QList & input_data) +template +QList +pcl::cloud_composer::OrganizedSegmentationTool::performTemplatedAction( + const QList& input_data) { - QList output; - - foreach (const CloudComposerItem* input_item, input_data) - { - QVariant variant = input_item->data (ItemDataRole::CLOUD_TEMPLATED); - if ( ! variant.canConvert ::Ptr> () ) - { - qWarning () << "Attempted to cast to template type which does not exist in this item! (input list)"; + QList output; + + foreach (const CloudComposerItem* input_item, input_data) { + QVariant variant = input_item->data(ItemDataRole::CLOUD_TEMPLATED); + if (!variant.canConvert::Ptr>()) { + qWarning() << "Attempted to cast to template type which does not exist in this " + "item! (input list)"; return output; } - typename PointCloud ::Ptr input_cloud = variant.value ::Ptr> (); - if ( ! input_cloud->isOrganized ()) - { - qCritical () << "Organized Segmentation requires an organized cloud!"; + typename PointCloud::Ptr input_cloud = + variant.value::Ptr>(); + if (!input_cloud->isOrganized()) { + qCritical() << "Organized Segmentation requires an organized cloud!"; return output; } } - int min_inliers = parameter_model_->getProperty ("Min Inliers").toInt (); - int min_plane_size = parameter_model_->getProperty ("Min Plane Size").toInt (); - double angular_threshold = parameter_model_->getProperty ("Angular Threshold").toDouble (); - double distance_threshold = parameter_model_->getProperty ("Distance Threshold").toDouble (); - double cluster_distance_threshold = parameter_model_->getProperty ("Cluster Dist. Thresh.").toDouble (); - int min_cluster_size = parameter_model_->getProperty ("Min Cluster Size").toInt (); - - foreach (const CloudComposerItem* input_item, input_data) - { - QList normals_list = input_item->getChildren (CloudComposerItem::NORMALS_ITEM); - //Get the normals cloud, we just use the first normals that were found if there are more than one - pcl::PointCloud::ConstPtr input_normals = normals_list.value(0)->data(ItemDataRole::CLOUD_TEMPLATED).value ::ConstPtr> (); - - QVariant variant = input_item->data (ItemDataRole::CLOUD_TEMPLATED); - typename PointCloud ::Ptr input_cloud = variant.value ::Ptr> (); + int min_inliers = parameter_model_->getProperty("Min Inliers").toInt(); + int min_plane_size = parameter_model_->getProperty("Min Plane Size").toInt(); + double angular_threshold = + parameter_model_->getProperty("Angular Threshold").toDouble(); + double distance_threshold = + parameter_model_->getProperty("Distance Threshold").toDouble(); + double cluster_distance_threshold = + parameter_model_->getProperty("Cluster Dist. Thresh.").toDouble(); + int min_cluster_size = parameter_model_->getProperty("Min Cluster Size").toInt(); + + foreach (const CloudComposerItem* input_item, input_data) { + QList normals_list = + input_item->getChildren(CloudComposerItem::NORMALS_ITEM); + // Get the normals cloud, we just use the first normals that were found if there are + // more than one + pcl::PointCloud::ConstPtr input_normals = + normals_list.value(0) + ->data(ItemDataRole::CLOUD_TEMPLATED) + .value::ConstPtr>(); + + QVariant variant = input_item->data(ItemDataRole::CLOUD_TEMPLATED); + typename PointCloud::Ptr input_cloud = + variant.value::Ptr>(); pcl::OrganizedMultiPlaneSegmentation mps; - mps.setMinInliers (min_inliers); - mps.setAngularThreshold (pcl::deg2rad (angular_threshold)); // convert to radians - mps.setDistanceThreshold (distance_threshold); - mps.setInputNormals (input_normals); - mps.setInputCloud (input_cloud); - std::vector, Eigen::aligned_allocator > > regions; + mps.setMinInliers(min_inliers); + mps.setAngularThreshold(pcl::deg2rad(angular_threshold)); // convert to radians + mps.setDistanceThreshold(distance_threshold); + mps.setInputNormals(input_normals); + mps.setInputCloud(input_cloud); + std::vector, + Eigen::aligned_allocator>> + regions; std::vector model_coefficients; std::vector inlier_indices; - pcl::PointCloud::Ptr labels (new pcl::PointCloud); + pcl::PointCloud::Ptr labels(new pcl::PointCloud); std::vector label_indices; std::vector boundary_indices; - mps.segmentAndRefine (regions, model_coefficients, inlier_indices, labels, label_indices, boundary_indices); - - auto plane_labels = pcl::make_shared > (); - for (std::size_t i = 0; i < label_indices.size (); ++i) - if (label_indices[i].indices.size () > (std::size_t) min_plane_size) - plane_labels->insert (i); + mps.segmentAndRefine(regions, + model_coefficients, + inlier_indices, + labels, + label_indices, + boundary_indices); + + auto plane_labels = pcl::make_shared>(); + for (std::size_t i = 0; i < label_indices.size(); ++i) + if (label_indices[i].indices.size() > (std::size_t)min_plane_size) + plane_labels->insert(i); typename PointCloud::CloudVectorType clusters; - typename EuclideanClusterComparator::Ptr euclidean_cluster_comparator(new EuclideanClusterComparator); - euclidean_cluster_comparator->setInputCloud (input_cloud); - euclidean_cluster_comparator->setLabels (labels); - euclidean_cluster_comparator->setExcludeLabels (plane_labels); - euclidean_cluster_comparator->setDistanceThreshold (cluster_distance_threshold, false); + typename EuclideanClusterComparator::Ptr + euclidean_cluster_comparator( + new EuclideanClusterComparator); + euclidean_cluster_comparator->setInputCloud(input_cloud); + euclidean_cluster_comparator->setLabels(labels); + euclidean_cluster_comparator->setExcludeLabels(plane_labels); + euclidean_cluster_comparator->setDistanceThreshold(cluster_distance_threshold, + false); pcl::PointCloud euclidean_labels; std::vector euclidean_label_indices; - pcl::OrganizedConnectedComponentSegmentation euclidean_segmentation (euclidean_cluster_comparator); - euclidean_segmentation.setInputCloud (input_cloud); - euclidean_segmentation.segment (euclidean_labels, euclidean_label_indices); - - pcl::IndicesPtr extracted_indices (new pcl::Indices ()); - for (std::size_t i = 0; i < euclidean_label_indices.size (); i++) - { - if (euclidean_label_indices[i].indices.size () >= (std::size_t) min_cluster_size) - { - typename PointCloud::Ptr cluster (new PointCloud); - pcl::copyPointCloud (*input_cloud,euclidean_label_indices[i].indices,*cluster); - qDebug () << "Found cluster with size " << cluster->width; - QString name = input_item->text () + tr ("- Clstr %1").arg (i); - CloudItem* new_cloud_item = CloudItem::createCloudItemFromTemplate(name,cluster); - output.append (new_cloud_item); - extracted_indices->insert (extracted_indices->end (), euclidean_label_indices[i].indices.begin (), euclidean_label_indices[i].indices.end ()); + pcl::OrganizedConnectedComponentSegmentation + euclidean_segmentation(euclidean_cluster_comparator); + euclidean_segmentation.setInputCloud(input_cloud); + euclidean_segmentation.segment(euclidean_labels, euclidean_label_indices); + + pcl::IndicesPtr extracted_indices(new pcl::Indices()); + for (std::size_t i = 0; i < euclidean_label_indices.size(); i++) { + if (euclidean_label_indices[i].indices.size() >= (std::size_t)min_cluster_size) { + typename PointCloud::Ptr cluster(new PointCloud); + pcl::copyPointCloud(*input_cloud, euclidean_label_indices[i].indices, *cluster); + qDebug() << "Found cluster with size " << cluster->width; + QString name = input_item->text() + tr("- Clstr %1").arg(i); + CloudItem* new_cloud_item = + CloudItem::createCloudItemFromTemplate(name, cluster); + output.append(new_cloud_item); + extracted_indices->insert(extracted_indices->end(), + euclidean_label_indices[i].indices.begin(), + euclidean_label_indices[i].indices.end()); } } - for (std::size_t i = 0; i < label_indices.size (); i++) - { - if (label_indices[i].indices.size () >= (std::size_t) min_plane_size) - { - typename PointCloud::Ptr plane (new PointCloud); - pcl::copyPointCloud (*input_cloud,label_indices[i].indices,*plane); - qDebug () << "Found plane with size " << plane->width; - QString name = input_item->text () + tr ("- Plane %1").arg (i); - CloudItem* new_cloud_item = CloudItem::createCloudItemFromTemplate(name,plane); - output.append (new_cloud_item); - extracted_indices->insert (extracted_indices->end (), label_indices[i].indices.begin (), label_indices[i].indices.end ()); - + for (std::size_t i = 0; i < label_indices.size(); i++) { + if (label_indices[i].indices.size() >= (std::size_t)min_plane_size) { + typename PointCloud::Ptr plane(new PointCloud); + pcl::copyPointCloud(*input_cloud, label_indices[i].indices, *plane); + qDebug() << "Found plane with size " << plane->width; + QString name = input_item->text() + tr("- Plane %1").arg(i); + CloudItem* new_cloud_item = + CloudItem::createCloudItemFromTemplate(name, plane); + output.append(new_cloud_item); + extracted_indices->insert(extracted_indices->end(), + label_indices[i].indices.begin(), + label_indices[i].indices.end()); } } - typename PointCloud::Ptr leftovers (new PointCloud); - if (extracted_indices->empty ()) - pcl::copyPointCloud (*input_cloud,*leftovers); - else - { + typename PointCloud::Ptr leftovers(new PointCloud); + if (extracted_indices->empty()) + pcl::copyPointCloud(*input_cloud, *leftovers); + else { pcl::ExtractIndices filter; - filter.setInputCloud (input_cloud); - filter.setIndices (extracted_indices); - filter.setNegative (true); - filter.filter (*leftovers); + filter.setInputCloud(input_cloud); + filter.setIndices(extracted_indices); + filter.setNegative(true); + filter.filter(*leftovers); } - CloudItem* leftover_cloud_item = CloudItem::createCloudItemFromTemplate(input_item->text(),leftovers); - output.append (leftover_cloud_item); + CloudItem* leftover_cloud_item = + CloudItem::createCloudItemFromTemplate(input_item->text(), leftovers); + output.append(leftover_cloud_item); } - - - return output; - } +#define PCL_INSTANTIATE_performTemplatedAction(T) \ + template void \ + pcl::cloud_composer::OrganizedSegmentationTool::performTemplatedAction( \ + QList); -#define PCL_INSTANTIATE_performTemplatedAction(T) template void pcl::cloud_composer::OrganizedSegmentationTool::performTemplatedAction (QList ); - - - -#endif //IMPL_TRANSFORM_CLOUDS_HPP_ +#endif // IMPL_TRANSFORM_CLOUDS_HPP_ diff --git a/apps/cloud_composer/include/pcl/apps/cloud_composer/tools/impl/supervoxels.hpp b/apps/cloud_composer/include/pcl/apps/cloud_composer/tools/impl/supervoxels.hpp index 2d83912f..4222f215 100644 --- a/apps/cloud_composer/include/pcl/apps/cloud_composer/tools/impl/supervoxels.hpp +++ b/apps/cloud_composer/include/pcl/apps/cloud_composer/tools/impl/supervoxels.hpp @@ -1,124 +1,117 @@ /* -* Software License Agreement (BSD License) -* -* Point Cloud Library (PCL) - www.pointclouds.org -* Copyright (c) 2012, Jeremie Papon. -* -* All rights reserved. -* -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions -* are met: -* -* * Redistributions of source code must retain the above copyright -* notice, this list of conditions and the following disclaimer. -* * Redistributions in binary form must reproduce the above -* copyright notice, this list of conditions and the following -* disclaimer in the documentation and/or other materials provided -* with the distribution. -* * Neither the name of Willow Garage, Inc. nor the names of its -* contributors may be used to endorse or promote products derived -* from this software without specific prior written permission. -* -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -* POSSIBILITY OF SUCH DAMAGE. -* -*/ + * Software License Agreement (BSD License) + * + * Point Cloud Library (PCL) - www.pointclouds.org + * Copyright (c) 2012, Jeremie Papon. + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of Willow Garage, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ #ifndef IMPL_SUPERVOXELS_HPP_ #define IMPL_SUPERVOXELS_HPP_ -#include #include #include +#include +#include #include #include -#include - -template QList -pcl::cloud_composer::SupervoxelsTool::performTemplatedAction (const QList & input_data) +template +QList +pcl::cloud_composer::SupervoxelsTool::performTemplatedAction( + const QList& input_data) { - QList output; - - foreach (const CloudComposerItem* input_item, input_data) - { - // if ( !input_item->isSanitized () ) - // { - // qCritical () << "SupervoxelsTool requires sanitized input!"; - // return output; - // } - QVariant variant = input_item->data (ItemDataRole::CLOUD_TEMPLATED); - if ( ! variant.canConvert ::Ptr> () ) - { - qWarning () << "Attempted to cast to template type which does not exist in this item! (input list)"; + QList output; + + foreach (const CloudComposerItem* input_item, input_data) { + // if ( !input_item->isSanitized () ) + // { + // qCritical () << "SupervoxelsTool requires sanitized input!"; + // return output; + // } + QVariant variant = input_item->data(ItemDataRole::CLOUD_TEMPLATED); + if (!variant.canConvert::Ptr>()) { + qWarning() << "Attempted to cast to template type which does not exist in this " + "item! (input list)"; return output; } - typename PointCloud ::Ptr input_cloud = variant.value ::Ptr> (); - //TODO: Check if Voxelized - -} - + typename PointCloud::Ptr input_cloud = + variant.value::Ptr>(); + // TODO: Check if Voxelized + } + + foreach (const CloudComposerItem* input_item, input_data) { + QVariant variant = input_item->data(ItemDataRole::CLOUD_TEMPLATED); + typename PointCloud::Ptr input_cloud = + variant.value::Ptr>(); + + float resolution = parameter_model_->getProperty("Resolution").toFloat(); + qDebug() << "Octree resolution = " << resolution; + float seed_resolution = parameter_model_->getProperty("Seed Resolution").toFloat(); + qDebug() << "Seed resolution = " << seed_resolution; + + float rgb_weight = parameter_model_->getProperty("RGB Weight").toFloat(); + float normal_weight = parameter_model_->getProperty("Normals Weight").toFloat(); + float spatial_weight = parameter_model_->getProperty("Spatial Weight").toFloat(); + + pcl::SupervoxelClustering super(resolution, seed_resolution); + super.setInputCloud(input_cloud); + super.setColorImportance(rgb_weight); + super.setSpatialImportance(spatial_weight); + super.setNormalImportance(normal_weight); + std::map::Ptr> supervoxel_clusters; + super.extract(supervoxel_clusters); + + std::map::Ptr> + refined_supervoxel_clusters; + super.refineSupervoxels(3, refined_supervoxel_clusters); - foreach (const CloudComposerItem* input_item, input_data) - { - QVariant variant = input_item->data (ItemDataRole::CLOUD_TEMPLATED); - typename PointCloud ::Ptr input_cloud = variant.value ::Ptr> (); - - float resolution = parameter_model_->getProperty("Resolution").toFloat (); - qDebug () << "Octree resolution = "<getProperty("Seed Resolution").toFloat (); - qDebug () << "Seed resolution = "<getProperty("RGB Weight").toFloat (); - float normal_weight = parameter_model_->getProperty("Normals Weight").toFloat (); - float spatial_weight = parameter_model_->getProperty("Spatial Weight").toFloat (); - - - pcl::SupervoxelClustering super (resolution, seed_resolution); - super.setInputCloud (input_cloud); - super.setColorImportance (rgb_weight); - super.setSpatialImportance (spatial_weight); - super.setNormalImportance (normal_weight); - std::map ::Ptr > supervoxel_clusters; - super.extract (supervoxel_clusters); - - std::map ::Ptr > refined_supervoxel_clusters; - super.refineSupervoxels (3, refined_supervoxel_clusters); - auto label_segments = super.getLabeledVoxelCloud(); auto color_segments = pcl::make_shared>(); pcl::copyPointCloud(*label_segments, *color_segments); for (size_t i = 0; i < label_segments->size(); ++i) - color_segments->at(i).rgba = GlasbeyLUT::at(label_segments->at(i).label % GlasbeyLUT::size()).rgba; - CloudItem* cloud_item_out = CloudItem::createCloudItemFromTemplate(input_item->text(), color_segments); - - output.append (cloud_item_out); - + color_segments->at(i).rgba = + GlasbeyLUT::at(label_segments->at(i).label % GlasbeyLUT::size()).rgba; + CloudItem* cloud_item_out = CloudItem::createCloudItemFromTemplate( + input_item->text(), color_segments); + + output.append(cloud_item_out); } - - - - + return output; - } +#define PCL_INSTANTIATE_performTemplatedAction(T) \ + template void pcl::cloud_composer::SupervoxelsTool::performTemplatedAction( \ + QList); - - -#define PCL_INSTANTIATE_performTemplatedAction(T) template void pcl::cloud_composer::SupervoxelsTool::performTemplatedAction (QList ); - - - -#endif //IMPL_SUPERVOXELS_HPP_ +#endif // IMPL_SUPERVOXELS_HPP_ diff --git a/apps/cloud_composer/include/pcl/apps/cloud_composer/tools/normal_estimation.h b/apps/cloud_composer/include/pcl/apps/cloud_composer/tools/normal_estimation.h index b5091cc0..cd27fbee 100644 --- a/apps/cloud_composer/include/pcl/apps/cloud_composer/tools/normal_estimation.h +++ b/apps/cloud_composer/include/pcl/apps/cloud_composer/tools/normal_estimation.h @@ -40,62 +40,68 @@ #include #include -namespace pcl -{ - namespace cloud_composer +namespace pcl { +namespace cloud_composer { +class NormalEstimationTool : public NewItemTool { + Q_OBJECT +public: + NormalEstimationTool(PropertiesModel* parameter_model, QObject* parent); + + QList + performAction(QList input_data, + PointTypeFlags::PointType type = PointTypeFlags::NONE) override; + + inline QString + getToolName() const override + { + return "Normal Estimation Tool"; + } +}; + +class NormalEstimationToolFactory : public QObject, public ToolFactory { + Q_OBJECT + Q_INTERFACES(pcl::cloud_composer::ToolFactory) + Q_PLUGIN_METADATA(IID "cloud_composer.ToolFactory/1.0") +public: + NewItemTool* + createTool(PropertiesModel* parameter_model, QObject* parent = nullptr) override + { + return new NormalEstimationTool(parameter_model, parent); + } + + PropertiesModel* + createToolParameterModel(QObject* parent) override; + + inline QString + getPluginName() const override { - class NormalEstimationTool : public NewItemTool - { - Q_OBJECT - public: - NormalEstimationTool (PropertiesModel* parameter_model, QObject* parent); - - QList - performAction (QList input_data, PointTypeFlags::PointType type = PointTypeFlags::NONE) override; - - inline QString - getToolName () const override { return "Normal Estimation Tool";} - }; + return "Normal Estimation"; + } - - class NormalEstimationToolFactory : public QObject, public ToolFactory - { - Q_OBJECT - Q_INTERFACES (pcl::cloud_composer::ToolFactory) - Q_PLUGIN_METADATA(IID "cloud_composer.ToolFactory/1.0") - public: - NewItemTool* - createTool (PropertiesModel* parameter_model, QObject* parent = nullptr) override - { - return new NormalEstimationTool(parameter_model, parent); - } - - PropertiesModel* - createToolParameterModel (QObject* parent) override; - - inline QString - getPluginName () const override { return "Normal Estimation";} - - QString - getToolGroupName () const override { return "Feature Estimation";} - - QString - getIconName () const override { return ":/normal_estimation.png"; } - - inline CloudComposerItem::ItemType - getInputItemType () const override - { - return CloudComposerItem::CLOUD_ITEM; - } - - inline QList - getRequiredInputChildrenTypes () const override - { - return QList (); - } - }; + QString + getToolGroupName() const override + { + return "Feature Estimation"; + } + QString + getIconName() const override + { + return ":/normal_estimation.png"; + } + inline CloudComposerItem::ItemType + getInputItemType() const override + { + return CloudComposerItem::CLOUD_ITEM; + } + inline QList + getRequiredInputChildrenTypes() const override + { + return QList(); } -} +}; + +} // namespace cloud_composer +} // namespace pcl diff --git a/apps/cloud_composer/include/pcl/apps/cloud_composer/tools/organized_segmentation.h b/apps/cloud_composer/include/pcl/apps/cloud_composer/tools/organized_segmentation.h index a35d946d..41aaf9e4 100644 --- a/apps/cloud_composer/include/pcl/apps/cloud_composer/tools/organized_segmentation.h +++ b/apps/cloud_composer/include/pcl/apps/cloud_composer/tools/organized_segmentation.h @@ -1,106 +1,112 @@ - /* - * Software License Agreement (BSD License) - * - * Point Cloud Library (PCL) - www.pointclouds.org - * Copyright (c) 2012, Jeremie Papon. - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials provided - * with the distribution. - * * Neither the name of Willow Garage, Inc. nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN - * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - +/* + * Software License Agreement (BSD License) + * + * Point Cloud Library (PCL) - www.pointclouds.org + * Copyright (c) 2012, Jeremie Papon. + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of Willow Garage, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ + #pragma once - - #include - #include - - - namespace pcl - { - namespace cloud_composer - { - class OrganizedSegmentationTool : public SplitItemTool - { - Q_OBJECT - public: - OrganizedSegmentationTool (PropertiesModel* parameter_model, QObject* parent); - - QList - performAction (QList input_data, PointTypeFlags::PointType type = PointTypeFlags::NONE) override; - - template QList - performTemplatedAction (const QList & input_data); - - inline QString - getToolName () const override { return "Organized Segmentation Tool";} - }; - - - class OrganizedSegmentationToolFactory : public QObject, public ToolFactory - { - Q_OBJECT - Q_INTERFACES (pcl::cloud_composer::ToolFactory) - Q_PLUGIN_METADATA(IID "cloud_composer.ToolFactory/1.0") - public: - SplitItemTool* - createTool (PropertiesModel* parameter_model, QObject* parent = nullptr) override - { - return new OrganizedSegmentationTool(parameter_model, parent); - } - - PropertiesModel* - createToolParameterModel (QObject* parent) override; - - inline QString - getPluginName () const override { return "Organized Segmentation";} - - inline QString - getToolGroupName () const override { return "Segmentation";} - - inline QString - getIconName () const override { return ":/organized_segmentation.png"; } - - inline CloudComposerItem::ItemType - getInputItemType () const override - { - return CloudComposerItem::CLOUD_ITEM; - } - - inline QList - getRequiredInputChildrenTypes () const override - { - QList input_types; - return (input_types << CloudComposerItem::NORMALS_ITEM); - } - }; - - - - } - } + +#include +#include + +namespace pcl { +namespace cloud_composer { +class OrganizedSegmentationTool : public SplitItemTool { + Q_OBJECT +public: + OrganizedSegmentationTool(PropertiesModel* parameter_model, QObject* parent); + + QList + performAction(QList input_data, + PointTypeFlags::PointType type = PointTypeFlags::NONE) override; + + template + QList + performTemplatedAction(const QList& input_data); + + inline QString + getToolName() const override + { + return "Organized Segmentation Tool"; + } +}; + +class OrganizedSegmentationToolFactory : public QObject, public ToolFactory { + Q_OBJECT + Q_INTERFACES(pcl::cloud_composer::ToolFactory) + Q_PLUGIN_METADATA(IID "cloud_composer.ToolFactory/1.0") +public: + SplitItemTool* + createTool(PropertiesModel* parameter_model, QObject* parent = nullptr) override + { + return new OrganizedSegmentationTool(parameter_model, parent); + } + + PropertiesModel* + createToolParameterModel(QObject* parent) override; + + inline QString + getPluginName() const override + { + return "Organized Segmentation"; + } + + inline QString + getToolGroupName() const override + { + return "Segmentation"; + } + + inline QString + getIconName() const override + { + return ":/organized_segmentation.png"; + } + + inline CloudComposerItem::ItemType + getInputItemType() const override + { + return CloudComposerItem::CLOUD_ITEM; + } + + inline QList + getRequiredInputChildrenTypes() const override + { + QList input_types; + return (input_types << CloudComposerItem::NORMALS_ITEM); + } +}; + +} // namespace cloud_composer +} // namespace pcl diff --git a/apps/cloud_composer/include/pcl/apps/cloud_composer/tools/sanitize_cloud.h b/apps/cloud_composer/include/pcl/apps/cloud_composer/tools/sanitize_cloud.h index f1c54653..2a8e33cc 100644 --- a/apps/cloud_composer/include/pcl/apps/cloud_composer/tools/sanitize_cloud.h +++ b/apps/cloud_composer/include/pcl/apps/cloud_composer/tools/sanitize_cloud.h @@ -40,62 +40,68 @@ #include #include -namespace pcl -{ - namespace cloud_composer +namespace pcl { +namespace cloud_composer { +class SanitizeCloudTool : public ModifyItemTool { + Q_OBJECT +public: + SanitizeCloudTool(PropertiesModel* parameter_model, QObject* parent); + + QList + performAction(QList input_data, + PointTypeFlags::PointType type = PointTypeFlags::NONE) override; + + inline QString + getToolName() const override + { + return "Sanitize Cloud Tool"; + } +}; + +class SanitizeCloudToolFactory : public QObject, public ToolFactory { + Q_OBJECT + Q_INTERFACES(pcl::cloud_composer::ToolFactory) + Q_PLUGIN_METADATA(IID "cloud_composer.ToolFactory/1.0") +public: + ModifyItemTool* + createTool(PropertiesModel* parameter_model, QObject* parent = nullptr) override + { + return new SanitizeCloudTool(parameter_model, parent); + } + + PropertiesModel* + createToolParameterModel(QObject* parent) override; + + inline QString + getPluginName() const override + { + return "Sanitize Cloud"; + } + + QString + getToolGroupName() const override + { + return "Filters"; + } + + QString + getIconName() const override { - class SanitizeCloudTool : public ModifyItemTool - { - Q_OBJECT - public: - SanitizeCloudTool (PropertiesModel* parameter_model, QObject* parent); - - QList - performAction (QList input_data, PointTypeFlags::PointType type = PointTypeFlags::NONE) override; - - inline QString - getToolName () const override { return "Sanitize Cloud Tool";} - }; - - - class SanitizeCloudToolFactory : public QObject, public ToolFactory - { - Q_OBJECT - Q_INTERFACES (pcl::cloud_composer::ToolFactory) - Q_PLUGIN_METADATA(IID "cloud_composer.ToolFactory/1.0") - public: - ModifyItemTool* - createTool (PropertiesModel* parameter_model, QObject* parent = nullptr) override - { - return new SanitizeCloudTool(parameter_model, parent); - } - - PropertiesModel* - createToolParameterModel (QObject* parent) override; - - inline QString - getPluginName () const override { return "Sanitize Cloud";} - - QString - getToolGroupName () const override { return "Filters";} - - QString - getIconName () const override { return ":/sanitize_cloud.png"; } - - inline CloudComposerItem::ItemType - getInputItemType () const override - { - return CloudComposerItem::CLOUD_ITEM; - } - - inline QList - getRequiredInputChildrenTypes () const override - { - return QList (); - } - }; - - - - } + return ":/sanitize_cloud.png"; } + + inline CloudComposerItem::ItemType + getInputItemType() const override + { + return CloudComposerItem::CLOUD_ITEM; + } + + inline QList + getRequiredInputChildrenTypes() const override + { + return QList(); + } +}; + +} // namespace cloud_composer +} // namespace pcl diff --git a/apps/cloud_composer/include/pcl/apps/cloud_composer/tools/statistical_outlier_removal.h b/apps/cloud_composer/include/pcl/apps/cloud_composer/tools/statistical_outlier_removal.h index 86ce2cbe..092edb06 100644 --- a/apps/cloud_composer/include/pcl/apps/cloud_composer/tools/statistical_outlier_removal.h +++ b/apps/cloud_composer/include/pcl/apps/cloud_composer/tools/statistical_outlier_removal.h @@ -40,63 +40,68 @@ #include #include +namespace pcl { +namespace cloud_composer { +class StatisticalOutlierRemovalTool : public ModifyItemTool { + Q_OBJECT +public: + StatisticalOutlierRemovalTool(PropertiesModel* parameter_model, QObject* parent); -namespace pcl -{ - namespace cloud_composer + QList + performAction(QList input_data, + PointTypeFlags::PointType type = PointTypeFlags::NONE) override; + + inline QString + getToolName() const override { - class StatisticalOutlierRemovalTool : public ModifyItemTool - { - Q_OBJECT - public: - StatisticalOutlierRemovalTool (PropertiesModel* parameter_model, QObject* parent); - - QList - performAction (QList input_data, PointTypeFlags::PointType type = PointTypeFlags::NONE) override; - - inline QString - getToolName () const override { return "Statistical Outlier Removal Tool";} - }; + return "Statistical Outlier Removal Tool"; + } +}; - - class StatisticalOutlierRemovalToolFactory : public QObject, public ToolFactory - { - Q_OBJECT - Q_INTERFACES (pcl::cloud_composer::ToolFactory) - Q_PLUGIN_METADATA(IID "cloud_composer.ToolFactory/1.0") - public: - ModifyItemTool* - createTool (PropertiesModel* parameter_model, QObject* parent = nullptr) override - { - return new StatisticalOutlierRemovalTool(parameter_model, parent); - } - - PropertiesModel* - createToolParameterModel (QObject* parent) override; - - inline QString - getPluginName () const override { return "Statistical Outlier Removal";} - - QString - getToolGroupName () const override { return "Filters";} - - QString - getIconName () const override { return ":/statistical_outlier_removal.png"; } - - inline CloudComposerItem::ItemType - getInputItemType () const override - { - return CloudComposerItem::CLOUD_ITEM; - } - - inline QList - getRequiredInputChildrenTypes () const override - { - return QList (); - } - }; +class StatisticalOutlierRemovalToolFactory : public QObject, public ToolFactory { + Q_OBJECT + Q_INTERFACES(pcl::cloud_composer::ToolFactory) + Q_PLUGIN_METADATA(IID "cloud_composer.ToolFactory/1.0") +public: + ModifyItemTool* + createTool(PropertiesModel* parameter_model, QObject* parent = nullptr) override + { + return new StatisticalOutlierRemovalTool(parameter_model, parent); + } + PropertiesModel* + createToolParameterModel(QObject* parent) override; + inline QString + getPluginName() const override + { + return "Statistical Outlier Removal"; + } + QString + getToolGroupName() const override + { + return "Filters"; } -} + + QString + getIconName() const override + { + return ":/statistical_outlier_removal.png"; + } + + inline CloudComposerItem::ItemType + getInputItemType() const override + { + return CloudComposerItem::CLOUD_ITEM; + } + + inline QList + getRequiredInputChildrenTypes() const override + { + return QList(); + } +}; + +} // namespace cloud_composer +} // namespace pcl diff --git a/apps/cloud_composer/include/pcl/apps/cloud_composer/tools/supervoxels.h b/apps/cloud_composer/include/pcl/apps/cloud_composer/tools/supervoxels.h index 39c6ea66..1383a599 100644 --- a/apps/cloud_composer/include/pcl/apps/cloud_composer/tools/supervoxels.h +++ b/apps/cloud_composer/include/pcl/apps/cloud_composer/tools/supervoxels.h @@ -1,108 +1,112 @@ - /* - * Software License Agreement (BSD License) - * - * Point Cloud Library (PCL) - www.pointclouds.org - * Copyright (c) 2012, Jeremie Papon. - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials provided - * with the distribution. - * * Neither the name of Willow Garage, Inc. nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN - * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - +/* + * Software License Agreement (BSD License) + * + * Point Cloud Library (PCL) - www.pointclouds.org + * Copyright (c) 2012, Jeremie Papon. + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of Willow Garage, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ + #pragma once - - #include - #include - - - namespace pcl - { - namespace cloud_composer - { - class SupervoxelsTool : public SplitItemTool - { - Q_OBJECT - public: - SupervoxelsTool (PropertiesModel* parameter_model, QObject* parent); - - QList - performAction (QList input_data, PointTypeFlags::PointType type = PointTypeFlags::NONE) override; - - template QList - performTemplatedAction (const QList & input_data); - - inline QString - getToolName () const override { return "Voxel Superpixels Tool";} - - - }; - - - class SupervoxelsToolFactory : public QObject, public ToolFactory - { - Q_OBJECT - Q_INTERFACES (pcl::cloud_composer::ToolFactory) - Q_PLUGIN_METADATA(IID "cloud_composer.ToolFactory/1.0") - public: - SplitItemTool* - createTool (PropertiesModel* parameter_model, QObject* parent = nullptr) override - { - return new SupervoxelsTool(parameter_model, parent); - } - - PropertiesModel* - createToolParameterModel (QObject* parent) override; - - inline QString - getPluginName () const override { return "Supervoxels";} - - inline QString - getToolGroupName () const override { return "Segmentation";} - - inline QString - getIconName () const override { return ":/supervoxels.png"; } - - inline CloudComposerItem::ItemType - getInputItemType () const override - { - return CloudComposerItem::CLOUD_ITEM; - } - - inline QList - getRequiredInputChildrenTypes () const override - { - QList input_types; - return input_types; - } - }; - - - - } - } + +#include +#include + +namespace pcl { +namespace cloud_composer { +class SupervoxelsTool : public SplitItemTool { + Q_OBJECT +public: + SupervoxelsTool(PropertiesModel* parameter_model, QObject* parent); + + QList + performAction(QList input_data, + PointTypeFlags::PointType type = PointTypeFlags::NONE) override; + + template + QList + performTemplatedAction(const QList& input_data); + + inline QString + getToolName() const override + { + return "Voxel Superpixels Tool"; + } +}; + +class SupervoxelsToolFactory : public QObject, public ToolFactory { + Q_OBJECT + Q_INTERFACES(pcl::cloud_composer::ToolFactory) + Q_PLUGIN_METADATA(IID "cloud_composer.ToolFactory/1.0") +public: + SplitItemTool* + createTool(PropertiesModel* parameter_model, QObject* parent = nullptr) override + { + return new SupervoxelsTool(parameter_model, parent); + } + + PropertiesModel* + createToolParameterModel(QObject* parent) override; + + inline QString + getPluginName() const override + { + return "Supervoxels"; + } + + inline QString + getToolGroupName() const override + { + return "Segmentation"; + } + + inline QString + getIconName() const override + { + return ":/supervoxels.png"; + } + + inline CloudComposerItem::ItemType + getInputItemType() const override + { + return CloudComposerItem::CLOUD_ITEM; + } + + inline QList + getRequiredInputChildrenTypes() const override + { + QList input_types; + return input_types; + } +}; + +} // namespace cloud_composer +} // namespace pcl diff --git a/apps/cloud_composer/include/pcl/apps/cloud_composer/tools/voxel_grid_downsample.h b/apps/cloud_composer/include/pcl/apps/cloud_composer/tools/voxel_grid_downsample.h index 85499ca8..8672be64 100644 --- a/apps/cloud_composer/include/pcl/apps/cloud_composer/tools/voxel_grid_downsample.h +++ b/apps/cloud_composer/include/pcl/apps/cloud_composer/tools/voxel_grid_downsample.h @@ -40,62 +40,68 @@ #include #include -namespace pcl -{ - namespace cloud_composer +namespace pcl { +namespace cloud_composer { +class VoxelGridDownsampleTool : public ModifyItemTool { + Q_OBJECT +public: + VoxelGridDownsampleTool(PropertiesModel* parameter_model, QObject* parent); + + QList + performAction(QList input_data, + PointTypeFlags::PointType type = PointTypeFlags::NONE) override; + + inline QString + getToolName() const override + { + return "Voxel Grid Downsample Tool"; + } +}; + +class VoxelGridDownsampleToolFactory : public QObject, public ToolFactory { + Q_OBJECT + Q_INTERFACES(pcl::cloud_composer::ToolFactory) + Q_PLUGIN_METADATA(IID "cloud_composer.ToolFactory/1.0") +public: + ModifyItemTool* + createTool(PropertiesModel* parameter_model, QObject* parent = nullptr) override + { + return new VoxelGridDownsampleTool(parameter_model, parent); + } + + PropertiesModel* + createToolParameterModel(QObject* parent) override; + + inline QString + getPluginName() const override { - class VoxelGridDownsampleTool : public ModifyItemTool - { - Q_OBJECT - public: - VoxelGridDownsampleTool (PropertiesModel* parameter_model, QObject* parent); - - QList - performAction (QList input_data, PointTypeFlags::PointType type = PointTypeFlags::NONE) override; - - inline QString - getToolName () const override { return "Voxel Grid Downsample Tool";} - }; + return "Voxel Grid Downsample"; + } - - class VoxelGridDownsampleToolFactory : public QObject, public ToolFactory - { - Q_OBJECT - Q_INTERFACES (pcl::cloud_composer::ToolFactory) - Q_PLUGIN_METADATA(IID "cloud_composer.ToolFactory/1.0") - public: - ModifyItemTool* - createTool (PropertiesModel* parameter_model, QObject* parent = nullptr) override - { - return new VoxelGridDownsampleTool(parameter_model, parent); - } - - PropertiesModel* - createToolParameterModel (QObject* parent) override; - - inline QString - getPluginName () const override { return "Voxel Grid Downsample";} - - QString - getToolGroupName () const override { return "Filters";} - - QString - getIconName () const override { return ":/voxel_grid_downsample.png"; } - - inline CloudComposerItem::ItemType - getInputItemType () const override - { - return CloudComposerItem::CLOUD_ITEM; - } - - inline QList - getRequiredInputChildrenTypes () const override - { - return QList (); - } - }; + QString + getToolGroupName() const override + { + return "Filters"; + } + QString + getIconName() const override + { + return ":/voxel_grid_downsample.png"; + } + inline CloudComposerItem::ItemType + getInputItemType() const override + { + return CloudComposerItem::CLOUD_ITEM; + } + inline QList + getRequiredInputChildrenTypes() const override + { + return QList(); } -} +}; + +} // namespace cloud_composer +} // namespace pcl diff --git a/apps/cloud_composer/include/pcl/apps/cloud_composer/transform_clouds.h b/apps/cloud_composer/include/pcl/apps/cloud_composer/transform_clouds.h index e2215296..e647b9f0 100644 --- a/apps/cloud_composer/include/pcl/apps/cloud_composer/transform_clouds.h +++ b/apps/cloud_composer/include/pcl/apps/cloud_composer/transform_clouds.h @@ -39,28 +39,31 @@ #include -namespace pcl -{ - namespace cloud_composer - { - class TransformClouds : public ModifyItemTool - { - Q_OBJECT - public: - TransformClouds (QMap > transform_map, QObject* parent = nullptr); - - QList - performAction (QList input_data, PointTypeFlags::PointType type = PointTypeFlags::NONE) override; - - inline QString - getToolName () const override { return "Transform Clouds Tool";} - - template QList - performTemplatedAction (const QList & input_data); - - private: - QMap > transform_map_; - }; +namespace pcl { +namespace cloud_composer { +class TransformClouds : public ModifyItemTool { + Q_OBJECT +public: + TransformClouds(QMap> transform_map, + QObject* parent = nullptr); + + QList + performAction(QList input_data, + PointTypeFlags::PointType type = PointTypeFlags::NONE) override; + inline QString + getToolName() const override + { + return "Transform Clouds Tool"; } -} + + template + QList + performTemplatedAction(const QList& input_data); + +private: + QMap> transform_map_; +}; + +} // namespace cloud_composer +} // namespace pcl diff --git a/apps/cloud_composer/include/pcl/apps/cloud_composer/work_queue.h b/apps/cloud_composer/include/pcl/apps/cloud_composer/work_queue.h index 95652a67..fb6227ca 100644 --- a/apps/cloud_composer/include/pcl/apps/cloud_composer/work_queue.h +++ b/apps/cloud_composer/include/pcl/apps/cloud_composer/work_queue.h @@ -37,47 +37,42 @@ #pragma once +#include + #include -#include +namespace pcl { +namespace cloud_composer { +class AbstractTool; +class CloudComposerItem; + +struct ActionPair { + CloudCommand* command; + AbstractTool* tool; +}; + +class WorkQueue : public QObject { + Q_OBJECT +public: + WorkQueue(QObject* parent = nullptr); +public Q_SLOTS: + void + enqueueNewAction(AbstractTool* new_tool, ConstItemList input_data); + + void + actionFinished(ActionPair finished_action); + + void + checkQueue(); +Q_SIGNALS: + void + commandProgress(QString command_text, double progress); -namespace pcl -{ - namespace cloud_composer - { - class AbstractTool; - class CloudComposerItem; - - struct ActionPair - { - CloudCommand* command; - AbstractTool* tool; - }; - - class WorkQueue : public QObject - { - Q_OBJECT - public: - WorkQueue (QObject* parent = nullptr); - public Q_SLOTS: - void - enqueueNewAction (AbstractTool* new_tool, ConstItemList input_data); - - void - actionFinished (ActionPair finished_action); - - void - checkQueue (); - Q_SIGNALS: - void - commandProgress (QString command_text, double progress); + void + commandComplete(CloudCommand* completed_command); - void - commandComplete (CloudCommand* completed_command); - - private: - QQueue work_queue_; - - }; - } -} +private: + QQueue work_queue_; +}; +} // namespace cloud_composer +} // namespace pcl diff --git a/apps/cloud_composer/src/cloud_composer.cpp b/apps/cloud_composer/src/cloud_composer.cpp index 1302b598..1c551d4d 100644 --- a/apps/cloud_composer/src/cloud_composer.cpp +++ b/apps/cloud_composer/src/cloud_composer.cpp @@ -1,14 +1,14 @@ #include -#include -#include #include -#include +#include #include -#include +#include +#include +#include +#include #include +#include #include -#include -#include #include #include @@ -16,215 +16,233 @@ #include ///////////////////////////////////////////////////////////// -pcl::cloud_composer::ComposerMainWindow::ComposerMainWindow (QWidget *parent) - : QMainWindow (parent) +pcl::cloud_composer::ComposerMainWindow::ComposerMainWindow(QWidget* parent) +: QMainWindow(parent) { - setupUi (this); - - this->setCorner (Qt::BottomLeftCorner, Qt::LeftDockWidgetArea); - this->setCorner (Qt::BottomRightCorner, Qt::RightDockWidgetArea); - - //Register types in Qt - qRegisterMetaType ("PCLPointCloud2Ptr"); - qRegisterMetaType ("GeometryHandlerConstPtr"); - qRegisterMetaType ("ColorHandlerConstPtr"); - qRegisterMetaType ("EigenVector4f"); - qRegisterMetaType ("EigenQuaternionf"); - qRegisterMetaType ("ProjectModel"); - qRegisterMetaType ("CloudView"); - qRegisterMetaType ("ConstComposerItemList"); - + setupUi(this); + + this->setCorner(Qt::BottomLeftCorner, Qt::LeftDockWidgetArea); + this->setCorner(Qt::BottomRightCorner, Qt::RightDockWidgetArea); + + // Register types in Qt + qRegisterMetaType("PCLPointCloud2Ptr"); + qRegisterMetaType("GeometryHandlerConstPtr"); + qRegisterMetaType("ColorHandlerConstPtr"); + qRegisterMetaType("EigenVector4f"); + qRegisterMetaType("EigenQuaternionf"); + qRegisterMetaType("ProjectModel"); + qRegisterMetaType("CloudView"); + qRegisterMetaType("ConstComposerItemList"); + current_model_ = nullptr; - - multiplexer_ = new SignalMultiplexer (this); - - initializeCloudBrowser (); - initializeCloudViewer (); - initializeItemInspector (); - initializeToolBox (); - initializePlugins (); - - undo_group_ = new QUndoGroup (this); - undo_view_->setGroup (undo_group_); - - //Auto connect signals and slots - // QMetaObject::connectSlotsByName(this); - connectFileActions (); - connectEditActions (); - connectViewActions (); - + + multiplexer_ = new SignalMultiplexer(this); + + initializeCloudBrowser(); + initializeCloudViewer(); + initializeItemInspector(); + initializeToolBox(); + initializePlugins(); + + undo_group_ = new QUndoGroup(this); + undo_view_->setGroup(undo_group_); + + // Auto connect signals and slots + // QMetaObject::connectSlotsByName(this); + connectFileActions(); + connectEditActions(); + connectViewActions(); } -pcl::cloud_composer::ComposerMainWindow::~ComposerMainWindow () +pcl::cloud_composer::ComposerMainWindow::~ComposerMainWindow() { - foreach (ProjectModel* to_delete, name_model_map_.values ()) - to_delete->deleteLater (); + foreach (ProjectModel* to_delete, name_model_map_.values()) + to_delete->deleteLater(); } void -pcl::cloud_composer::ComposerMainWindow::connectFileActions () -{ - - -} +pcl::cloud_composer::ComposerMainWindow::connectFileActions() +{} void -pcl::cloud_composer::ComposerMainWindow::connectEditActions () +pcl::cloud_composer::ComposerMainWindow::connectEditActions() { - //Replace the actions in the menu with undo actions created using the undo group - QAction* action_temp = undo_group_->createUndoAction (this); - action_temp->setShortcut (action_undo_->shortcut ()); - menuEdit->insertAction (action_redo_, action_temp); - menuEdit->removeAction (action_undo_); + // Replace the actions in the menu with undo actions created using the undo group + QAction* action_temp = undo_group_->createUndoAction(this); + action_temp->setShortcut(action_undo_->shortcut()); + menuEdit->insertAction(action_redo_, action_temp); + menuEdit->removeAction(action_undo_); action_undo_ = action_temp; - - action_temp = undo_group_->createRedoAction (this); - action_temp->setShortcut (action_redo_->shortcut ()); - menuEdit->insertAction (action_redo_, action_temp); - menuEdit->removeAction (action_redo_); + + action_temp = undo_group_->createRedoAction(this); + action_temp->setShortcut(action_redo_->shortcut()); + menuEdit->insertAction(action_redo_, action_temp); + menuEdit->removeAction(action_redo_); action_redo_ = action_temp; - - multiplexer_->connect (action_clear_selection_, SIGNAL (triggered ()), SLOT (clearSelection ())); - - multiplexer_->connect (action_delete_, SIGNAL (triggered ()), SLOT (deleteSelectedItems ())); - multiplexer_->connect (SIGNAL (deleteAvailable (bool)), action_delete_, SLOT (setEnabled (bool))); - - multiplexer_->connect (this, SIGNAL (insertNewCloudFromFile()), SLOT (insertNewCloudFromFile())); - multiplexer_->connect (this, SIGNAL (insertNewCloudFromRGBandDepth()), SLOT (insertNewCloudFromRGBandDepth())); - multiplexer_->connect (this, SIGNAL (saveSelectedCloudToFile()), SLOT (saveSelectedCloudToFile())); - - - mouse_style_group_ = new QActionGroup (this); - mouse_style_group_->addAction (action_trackball_camera_style_); - mouse_style_group_->addAction (action_manipulate_clicked_); - mouse_style_group_->addAction (action_manipulate_selected_); - mouse_style_group_->addAction (action_rectangular_frustum_select_); - mouse_style_group_->setExclusive (true); - multiplexer_->connect (mouse_style_group_, SIGNAL (triggered (QAction*)), SLOT (mouseStyleChanged (QAction*))); - multiplexer_->connect(SIGNAL (mouseStyleState (interactor_styles::INTERACTOR_STYLES)), this, SLOT(setMouseStyleAction(interactor_styles::INTERACTOR_STYLES))); - action_trackball_camera_style_->setData (QVariant::fromValue (interactor_styles::PCL_VISUALIZER)); - action_rectangular_frustum_select_->setData (QVariant::fromValue (interactor_styles::RECTANGULAR_FRUSTUM)); - action_manipulate_selected_->setData (QVariant::fromValue (interactor_styles::SELECTED_TRACKBALL)); - action_manipulate_clicked_->setData (QVariant::fromValue (interactor_styles::CLICK_TRACKBALL)); - //multiplexer_->connect (action_manipulate_selected_, SIGNAL (triggered ()), SLOT (selectedTrackballInteractorStyle ())); - - - multiplexer_->connect (action_new_cloud_from_selection_, SIGNAL (triggered ()), SLOT (createNewCloudFromSelection ())); - multiplexer_->connect (SIGNAL (newCloudFromSelectionAvailable (bool)), action_new_cloud_from_selection_, SLOT (setEnabled (bool))); - - multiplexer_->connect (action_select_all_, SIGNAL (triggered ()), SLOT (selectAllItems ())); + + multiplexer_->connect( + action_clear_selection_, SIGNAL(triggered()), SLOT(clearSelection())); + + multiplexer_->connect( + action_delete_, SIGNAL(triggered()), SLOT(deleteSelectedItems())); + multiplexer_->connect( + SIGNAL(deleteAvailable(bool)), action_delete_, SLOT(setEnabled(bool))); + + multiplexer_->connect( + this, SIGNAL(insertNewCloudFromFile()), SLOT(insertNewCloudFromFile())); + multiplexer_->connect(this, + SIGNAL(insertNewCloudFromRGBandDepth()), + SLOT(insertNewCloudFromRGBandDepth())); + multiplexer_->connect( + this, SIGNAL(saveSelectedCloudToFile()), SLOT(saveSelectedCloudToFile())); + + mouse_style_group_ = new QActionGroup(this); + mouse_style_group_->addAction(action_trackball_camera_style_); + mouse_style_group_->addAction(action_manipulate_clicked_); + mouse_style_group_->addAction(action_manipulate_selected_); + mouse_style_group_->addAction(action_rectangular_frustum_select_); + mouse_style_group_->setExclusive(true); + multiplexer_->connect(mouse_style_group_, + SIGNAL(triggered(QAction*)), + SLOT(mouseStyleChanged(QAction*))); + multiplexer_->connect( + SIGNAL(mouseStyleState(interactor_styles::INTERACTOR_STYLES)), + this, + SLOT(setMouseStyleAction(interactor_styles::INTERACTOR_STYLES))); + action_trackball_camera_style_->setData( + QVariant::fromValue(interactor_styles::PCL_VISUALIZER)); + action_rectangular_frustum_select_->setData( + QVariant::fromValue(interactor_styles::RECTANGULAR_FRUSTUM)); + action_manipulate_selected_->setData( + QVariant::fromValue(interactor_styles::SELECTED_TRACKBALL)); + action_manipulate_clicked_->setData( + QVariant::fromValue(interactor_styles::CLICK_TRACKBALL)); + // multiplexer_->connect (action_manipulate_selected_, SIGNAL (triggered ()), SLOT + // (selectedTrackballInteractorStyle ())); + + multiplexer_->connect(action_new_cloud_from_selection_, + SIGNAL(triggered()), + SLOT(createNewCloudFromSelection())); + multiplexer_->connect(SIGNAL(newCloudFromSelectionAvailable(bool)), + action_new_cloud_from_selection_, + SLOT(setEnabled(bool))); + + multiplexer_->connect( + action_select_all_, SIGNAL(triggered()), SLOT(selectAllItems())); } void -pcl::cloud_composer::ComposerMainWindow::setMouseStyleAction (interactor_styles::INTERACTOR_STYLES selected_style) +pcl::cloud_composer::ComposerMainWindow::setMouseStyleAction( + interactor_styles::INTERACTOR_STYLES selected_style) { - action_trackball_camera_style_->setChecked (false); - action_rectangular_frustum_select_->setChecked (false); - action_manipulate_selected_->setChecked (false); - action_manipulate_clicked_->setChecked (false); - - switch (selected_style) - { - case interactor_styles::PCL_VISUALIZER : - action_trackball_camera_style_->setChecked (true); - break; - case interactor_styles::CLICK_TRACKBALL : - action_manipulate_clicked_->setChecked (true); - break; - case interactor_styles::RECTANGULAR_FRUSTUM : - action_rectangular_frustum_select_->setChecked (true); - break; - case interactor_styles::SELECTED_TRACKBALL : - action_manipulate_selected_->setChecked (true); - break; - default : - action_trackball_camera_style_->setChecked (true); - + action_trackball_camera_style_->setChecked(false); + action_rectangular_frustum_select_->setChecked(false); + action_manipulate_selected_->setChecked(false); + action_manipulate_clicked_->setChecked(false); + + switch (selected_style) { + case interactor_styles::PCL_VISUALIZER: + action_trackball_camera_style_->setChecked(true); + break; + case interactor_styles::CLICK_TRACKBALL: + action_manipulate_clicked_->setChecked(true); + break; + case interactor_styles::RECTANGULAR_FRUSTUM: + action_rectangular_frustum_select_->setChecked(true); + break; + case interactor_styles::SELECTED_TRACKBALL: + action_manipulate_selected_->setChecked(true); + break; + default: + action_trackball_camera_style_->setChecked(true); } } void -pcl::cloud_composer::ComposerMainWindow::connectViewActions () +pcl::cloud_composer::ComposerMainWindow::connectViewActions() { - multiplexer_->connect (action_show_axes_, SIGNAL (toggled (bool)), SLOT (setAxisVisibility (bool))); - multiplexer_->connect (SIGNAL (axisVisible (bool)), action_show_axes_, SLOT (setChecked (bool))); - + multiplexer_->connect( + action_show_axes_, SIGNAL(toggled(bool)), SLOT(setAxisVisibility(bool))); + multiplexer_->connect( + SIGNAL(axisVisible(bool)), action_show_axes_, SLOT(setChecked(bool))); } void -pcl::cloud_composer::ComposerMainWindow::initializeCloudBrowser () +pcl::cloud_composer::ComposerMainWindow::initializeCloudBrowser() { - cloud_browser_->setSelectionMode (QAbstractItemView::ExtendedSelection); - + cloud_browser_->setSelectionMode(QAbstractItemView::ExtendedSelection); + cloud_browser_->setStyleSheet("selection-background-color: red;"); - } void -pcl::cloud_composer::ComposerMainWindow::initializeCloudViewer () +pcl::cloud_composer::ComposerMainWindow::initializeCloudViewer() { - //Signal emitted when user selects new tab (ie different project) in the viewer - connect (cloud_viewer_, SIGNAL (newModelSelected (ProjectModel*)), - this, SLOT (setCurrentModel (ProjectModel*))); - + // Signal emitted when user selects new tab (ie different project) in the viewer + connect(cloud_viewer_, + SIGNAL(newModelSelected(ProjectModel*)), + this, + SLOT(setCurrentModel(ProjectModel*))); } void -pcl::cloud_composer::ComposerMainWindow::initializeItemInspector () -{ - -} +pcl::cloud_composer::ComposerMainWindow::initializeItemInspector() +{} void -pcl::cloud_composer::ComposerMainWindow::initializeToolBox () +pcl::cloud_composer::ComposerMainWindow::initializeToolBox() { - tool_box_model_ = new ToolBoxModel (tool_box_view_, tool_parameter_view_,this); - tool_selection_model_ = new QItemSelectionModel (tool_box_model_); - tool_box_model_->setSelectionModel (tool_selection_model_); - - tool_box_view_->setModel (tool_box_model_); - tool_box_view_->setSelectionModel (tool_selection_model_); - tool_box_view_->setIconSize (QSize (32,32)); - tool_box_view_->setIndentation (10); - - connect ( tool_selection_model_, SIGNAL (currentChanged (const QModelIndex&, const QModelIndex&)), - tool_box_model_, SLOT (selectedToolChanged (const QModelIndex&, const QModelIndex&))); - - connect ( tool_box_model_, SIGNAL (enqueueToolAction (AbstractTool*)), - this, SLOT (enqueueToolAction (AbstractTool*))); - - connect (this, SIGNAL (activeProjectChanged (ProjectModel*,ProjectModel*)), - tool_box_model_, SLOT (activeProjectChanged (ProjectModel*,ProjectModel*))); - - //TODO : Remove this, tools should have a better way of being run - connect ( action_run_tool_, SIGNAL (clicked ()), - tool_box_model_, SLOT (toolAction ())); - //tool_box_view_->setStyleSheet("branch:has-siblings:!adjoins-item:image none"); - // tool_box_view_->setStyleSheet("branch:!has-children:!has-siblings:adjoins-item:image: none"); - - + tool_box_model_ = new ToolBoxModel(tool_box_view_, tool_parameter_view_, this); + tool_selection_model_ = new QItemSelectionModel(tool_box_model_); + tool_box_model_->setSelectionModel(tool_selection_model_); + + tool_box_view_->setModel(tool_box_model_); + tool_box_view_->setSelectionModel(tool_selection_model_); + tool_box_view_->setIconSize(QSize(32, 32)); + tool_box_view_->setIndentation(10); + + connect(tool_selection_model_, + SIGNAL(currentChanged(const QModelIndex&, const QModelIndex&)), + tool_box_model_, + SLOT(selectedToolChanged(const QModelIndex&, const QModelIndex&))); + + connect(tool_box_model_, + SIGNAL(enqueueToolAction(AbstractTool*)), + this, + SLOT(enqueueToolAction(AbstractTool*))); + + connect(this, + SIGNAL(activeProjectChanged(ProjectModel*, ProjectModel*)), + tool_box_model_, + SLOT(activeProjectChanged(ProjectModel*, ProjectModel*))); + + // TODO : Remove this, tools should have a better way of being run + connect(action_run_tool_, SIGNAL(clicked()), tool_box_model_, SLOT(toolAction())); + // tool_box_view_->setStyleSheet("branch:has-siblings:!adjoins-item:image none"); + // tool_box_view_->setStyleSheet("branch:!has-children:!has-siblings:adjoins-item:image: + // none"); } - -void -pcl::cloud_composer::ComposerMainWindow::initializePlugins () +void +pcl::cloud_composer::ComposerMainWindow::initializePlugins() { - QDir plugin_dir = QCoreApplication::applicationDirPath (); - qDebug() << plugin_dir.path ()<< " "< (plugin); + QObject* plugin = loader.instance(); + ToolFactory* tool_factory = qobject_cast(plugin); if (tool_factory) { - qWarning () << "Loaded " << tool_factory->getPluginName (); - //Create the action button for this tool - tool_box_model_->addTool (tool_factory); - + qWarning() << "Loaded " << tool_factory->getPluginName(); + // Create the action button for this tool + tool_box_model_->addTool(tool_factory); } - else{ - qDebug() << "Could not load " << plugin_dir.relativeFilePath (filename); - qDebug() << loader.errorString (); + else { + qDebug() << "Could not load " << plugin_dir.relativeFilePath(filename); + qDebug() << loader.errorString(); } - } } - - -void -pcl::cloud_composer::ComposerMainWindow::setCurrentModel (ProjectModel* model) +void +pcl::cloud_composer::ComposerMainWindow::setCurrentModel(ProjectModel* model) { - emit activeProjectChanged (model, current_model_); + emit activeProjectChanged(model, current_model_); current_model_ = model; - //qDebug () << "Setting cloud browser model"; - cloud_browser_->setModel (current_model_); - //qDebug () << "Setting cloud browser selection model"; - cloud_browser_->setSelectionModel (current_model_->getSelectionModel ()); - //qDebug () << "Item inspector setting model"; - item_inspector_->setModel (current_model_); - //qDebug () << "Setting active stack in undo group"; - undo_group_->setActiveStack (current_model_->getUndoStack ()); - - multiplexer_->setCurrentObject (current_model_); + // qDebug () << "Setting cloud browser model"; + cloud_browser_->setModel(current_model_); + // qDebug () << "Setting cloud browser selection model"; + cloud_browser_->setSelectionModel(current_model_->getSelectionModel()); + // qDebug () << "Item inspector setting model"; + item_inspector_->setModel(current_model_); + // qDebug () << "Setting active stack in undo group"; + undo_group_->setActiveStack(current_model_->getUndoStack()); + + multiplexer_->setCurrentObject(current_model_); } void -pcl::cloud_composer::ComposerMainWindow::enqueueToolAction (AbstractTool* tool) +pcl::cloud_composer::ComposerMainWindow::enqueueToolAction(AbstractTool* tool) { if (current_model_) - current_model_->enqueueToolAction (tool); + current_model_->enqueueToolAction(tool); else - QMessageBox::warning (this, "No Project Open!", "Cannot use tool, no project is open!"); + QMessageBox::warning( + this, "No Project Open!", "Cannot use tool, no project is open!"); } ///////// FILE MENU SLOTS /////////// -void -pcl::cloud_composer::ComposerMainWindow::on_action_new_project__triggered (/*QString name*/) +void pcl::cloud_composer::ComposerMainWindow::on_action_new_project__triggered( + /*QString name*/) { QString name("unsaved project"); - qDebug () << "Creating New Project"; - ProjectModel* new_project_model = new ProjectModel (this); + qDebug() << "Creating New Project"; + ProjectModel* new_project_model = new ProjectModel(this); // Check if we have a project with this name already, append int if so - if (name_model_map_.contains (name)) - { + if (name_model_map_.contains(name)) { int k = 2; - while (name_model_map_.contains (name + tr ("-%1").arg (k))) + while (name_model_map_.contains(name + tr("-%1").arg(k))) ++k; - name += tr ("-%1").arg (k); + name += tr("-%1").arg(k); } - //qDebug () << "Setting name"; - new_project_model->setName (name); - //qDebug () << "Inserting into map"; - name_model_map_.insert (name,new_project_model); - //qDebug () << "Adding to undo group"; - undo_group_->addStack (new_project_model->getUndoStack ()); - //qDebug () << "Setting current model"; - cloud_viewer_->addNewProject (new_project_model); - - setCurrentModel (new_project_model); - //qDebug () << "Project " <setName(name); + // qDebug () << "Inserting into map"; + name_model_map_.insert(name, new_project_model); + // qDebug () << "Adding to undo group"; + undo_group_->addStack(new_project_model->getUndoStack()); + // qDebug () << "Setting current model"; + cloud_viewer_->addNewProject(new_project_model); + + setCurrentModel(new_project_model); + // qDebug () << "Project " <trigger (); - - emit insertNewCloudFromFile (); + action_new_project_->trigger(); + + emit insertNewCloudFromFile(); } void -pcl::cloud_composer::ComposerMainWindow::on_action_insert_from_rgb_depth__triggered () +pcl::cloud_composer::ComposerMainWindow::on_action_insert_from_rgb_depth__triggered() { if (!current_model_) - action_new_project_->trigger (); - - emit insertNewCloudFromRGBandDepth (); -} + action_new_project_->trigger(); + emit insertNewCloudFromRGBandDepth(); +} void -pcl::cloud_composer::ComposerMainWindow::on_action_insert_from_openNi_source__triggered () +pcl::cloud_composer::ComposerMainWindow:: + on_action_insert_from_openNi_source__triggered() { - qDebug () << "Inserting cloud from OpenNi Source..."; + qDebug() << "Inserting cloud from OpenNi Source..."; } - - - diff --git a/apps/cloud_composer/src/cloud_viewer.cpp b/apps/cloud_composer/src/cloud_viewer.cpp index f47c1c05..1479ef25 100644 --- a/apps/cloud_composer/src/cloud_viewer.cpp +++ b/apps/cloud_composer/src/cloud_viewer.cpp @@ -1,66 +1,62 @@ +#include #include #include -#include #include -pcl::cloud_composer::CloudViewer::CloudViewer (QWidget* parent) - : QTabWidget (parent) +pcl::cloud_composer::CloudViewer::CloudViewer(QWidget* parent) : QTabWidget(parent) { - connect (this, SIGNAL (currentChanged (int)), - this, SLOT (modelChanged (int))); + connect(this, SIGNAL(currentChanged(int)), this, SLOT(modelChanged(int))); } void -pcl::cloud_composer::CloudViewer::addModel (ProjectModel* new_model) +pcl::cloud_composer::CloudViewer::addModel(ProjectModel* new_model) { - CloudView* new_view = new CloudView (new_model); - connect (new_model->getSelectionModel (), SIGNAL (selectionChanged (QItemSelection,QItemSelection)), - new_view, SLOT (selectedItemChanged (QItemSelection,QItemSelection))); - new_model->setCloudView (new_view); - - QStandardItem* title = new_model->horizontalHeaderItem (0); - this->addTab (new_view, title->text ()); - - model_view_map_.insert (new_model,new_view); - - setCurrentWidget (model_view_map_.value (new_model)); - //Refresh the view - new_view->refresh (); + CloudView* new_view = new CloudView(new_model); + connect(new_model->getSelectionModel(), + SIGNAL(selectionChanged(QItemSelection, QItemSelection)), + new_view, + SLOT(selectedItemChanged(QItemSelection, QItemSelection))); + new_model->setCloudView(new_view); + + QStandardItem* title = new_model->horizontalHeaderItem(0); + this->addTab(new_view, title->text()); + model_view_map_.insert(new_model, new_view); + + setCurrentWidget(model_view_map_.value(new_model)); + // Refresh the view + new_view->refresh(); } - + pcl::cloud_composer::ProjectModel* -pcl::cloud_composer::CloudViewer::getModel () const +pcl::cloud_composer::CloudViewer::getModel() const { if (this->count() == 0) return nullptr; - return dynamic_cast (currentWidget ())->getModel (); + return dynamic_cast(currentWidget())->getModel(); } void -pcl::cloud_composer::CloudViewer::addNewProject (ProjectModel* new_model) +pcl::cloud_composer::CloudViewer::addNewProject(ProjectModel* new_model) { - //If we're already there, abort - if (new_model == getModel ()) + // If we're already there, abort + if (new_model == getModel()) return; - //Check whether we've seen the model yet - if ( !model_view_map_.contains (new_model)) - { - addModel (new_model); + // Check whether we've seen the model yet + if (!model_view_map_.contains(new_model)) { + addModel(new_model); } - else - { - setCurrentWidget (model_view_map_.value (new_model)); - //Refresh the view - model_view_map_.value (new_model)->refresh (); + else { + setCurrentWidget(model_view_map_.value(new_model)); + // Refresh the view + model_view_map_.value(new_model)->refresh(); } } void -pcl::cloud_composer::CloudViewer::modelChanged (int) +pcl::cloud_composer::CloudViewer::modelChanged(int) { - emit newModelSelected (getModel ()); + emit newModelSelected(getModel()); } - diff --git a/apps/cloud_composer/src/commands.cpp b/apps/cloud_composer/src/commands.cpp index c8a0b973..03ff9c15 100644 --- a/apps/cloud_composer/src/commands.cpp +++ b/apps/cloud_composer/src/commands.cpp @@ -1,38 +1,32 @@ #include -#include -#include #include +#include +#include -pcl::cloud_composer::CloudCommand::CloudCommand (QList input_data, QUndoCommand* parent) - : QUndoCommand (parent) - , original_data_ (std::move(input_data)) - , can_use_templates_(false) - , template_type_ (-1) -{ - -} +pcl::cloud_composer::CloudCommand::CloudCommand( + QList input_data, QUndoCommand* parent) +: QUndoCommand(parent) +, original_data_(std::move(input_data)) +, can_use_templates_(false) +, template_type_(-1) +{} -pcl::cloud_composer::CloudCommand::~CloudCommand () +pcl::cloud_composer::CloudCommand::~CloudCommand() { - qDebug () << "Command Destructor"; - //If we have removed items, we delete them - if (!last_was_undo_) - { - qDebug () << "Last was redo, removing original items "; - QList items_to_remove = removed_to_parent_map_.keys (); - foreach (QStandardItem* to_remove, items_to_remove) - { - delete to_remove; + qDebug() << "Command Destructor"; + // If we have removed items, we delete them + if (!last_was_undo_) { + qDebug() << "Last was redo, removing original items "; + QList items_to_remove = removed_to_parent_map_.keys(); + foreach (QStandardItem* to_remove, items_to_remove) { + delete to_remove; } } - else - { - qDebug () << "Last was undo, removing new items"; - foreach (OutputPair output_pair, output_data_) - { - QList new_items = output_pair.output_items_; - foreach (CloudComposerItem* item, new_items) - { + else { + qDebug() << "Last was undo, removing new items"; + foreach (OutputPair output_pair, output_data_) { + QList new_items = output_pair.output_items_; + foreach (CloudComposerItem* item, new_items) { delete item; } } @@ -41,44 +35,43 @@ pcl::cloud_composer::CloudCommand::~CloudCommand () ////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void -pcl::cloud_composer::CloudCommand::setProjectModel (ProjectModel* model) +pcl::cloud_composer::CloudCommand::setProjectModel(ProjectModel* model) { project_model_ = model; } bool -pcl::cloud_composer::CloudCommand::canUseTemplates (ConstItemList &input_data) +pcl::cloud_composer::CloudCommand::canUseTemplates(ConstItemList& input_data) { - //Make sure the input list isn't empty - if (input_data.empty ()) - { - qCritical () << "Cannot call a templated tool on an empty input in CloudCommand::executeToolOnTemplateCloud!"; + // Make sure the input list isn't empty + if (input_data.empty()) { + qCritical() << "Cannot call a templated tool on an empty input in " + "CloudCommand::executeToolOnTemplateCloud!"; template_type_ = -2; return false; } - //Make sure all input items are clouds - QList cloud_items; - foreach (const CloudComposerItem* item, input_data) - { - const CloudItem* cloud_item = dynamic_cast (item); + // Make sure all input items are clouds + QList cloud_items; + foreach (const CloudComposerItem* item, input_data) { + const CloudItem* cloud_item = dynamic_cast(item); if (cloud_item) - cloud_items.append (cloud_item); + cloud_items.append(cloud_item); } - if (cloud_items.size () != input_data.size ()) - { - qCritical () << "All input items are not clouds in CloudCommand::executeToolOnTemplateCloud!"; + if (cloud_items.size() != input_data.size()) { + qCritical() << "All input items are not clouds in " + "CloudCommand::executeToolOnTemplateCloud!"; template_type_ = -3; return false; } - + // Now make sure all input clouds have the same templated type - int type = cloud_items.value (0)->getPointType (); - foreach (const CloudItem* cloud_item, cloud_items) - { - if (cloud_item->getPointType () != type) - { - qCritical () << "All input point cloud template types in CloudCommand::executeToolOnTemplateCloud are not the same!"; - qCritical () << cloud_item->text () << "'s type does not match "<type (); + int type = cloud_items.value(0)->getPointType(); + foreach (const CloudItem* cloud_item, cloud_items) { + if (cloud_item->getPointType() != type) { + qCritical() << "All input point cloud template types in " + "CloudCommand::executeToolOnTemplateCloud are not the same!"; + qCritical() << cloud_item->text() << "'s type does not match " + << cloud_items.value(0)->type(); template_type_ = -3; return false; } @@ -89,111 +82,114 @@ pcl::cloud_composer::CloudCommand::canUseTemplates (ConstItemList &input_data) } /* -QList -pcl::cloud_composer::CloudCommand::executeToolOnTemplateCloud (AbstractTool* tool, ConstItemList &input_data) +QList +pcl::cloud_composer::CloudCommand::executeToolOnTemplateCloud (AbstractTool* tool, +ConstItemList &input_data) { QList output; // If can_use_templates_ is false and type is -1 we haven't checked if we can yet if (!can_use_templates_ && template_type_ == -1) this->canUseTemplates (input_data); - - + + //If this is true now, we can go ahead and run it if (can_use_templates_ && template_type_ >= 0) { - output = tool->performAction( input_data, static_cast (template_type_)); + output = tool->performAction( input_data, static_cast +(template_type_)); } else { - qDebug () << "Tried CloudCommand::executeToolOnTemplateCloud but input data was not templated clouds!"; + qDebug () << "Tried CloudCommand::executeToolOnTemplateCloud but input data was not +templated clouds!"; } return output; - + } */ ////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -bool -pcl::cloud_composer::CloudCommand::replaceOriginalWithNew (const QList & originals, const QList & new_items) -{ - //Find the input item's parent - if (originals.empty ()) - { - qCritical () << "No items to replace specified!"; +bool +pcl::cloud_composer::CloudCommand::replaceOriginalWithNew( + const QList& originals, + const QList& new_items) +{ + // Find the input item's parent + if (originals.empty()) { + qCritical() << "No items to replace specified!"; return false; } - - QStandardItem* parent_item = originals.value(0)->parent (); - //Verify that all items have same parent - foreach (const CloudComposerItem* item, originals) - { - if (item->parent () != parent_item) - { - qCritical () << "All original items must have same parent!"; + + QStandardItem* parent_item = originals.value(0)->parent(); + // Verify that all items have same parent + foreach (const CloudComposerItem* item, originals) { + if (item->parent() != parent_item) { + qCritical() << "All original items must have same parent!"; return false; } } // If parent is 0, it's parent is invisiblerootitem (That's how Qt defines it... boo!) if (parent_item == nullptr) - parent_item = project_model_->invisibleRootItem (); - - //Now remove all the originals - foreach (const CloudComposerItem* item, originals) - { - QPersistentModelIndex original_index = QPersistentModelIndex(project_model_->indexFromItem (item)); - if (!original_index.isValid ()) - { - qCritical () << "Index of item to replace is not valid!"; + parent_item = project_model_->invisibleRootItem(); + + // Now remove all the originals + foreach (const CloudComposerItem* item, originals) { + QPersistentModelIndex original_index = + QPersistentModelIndex(project_model_->indexFromItem(item)); + if (!original_index.isValid()) { + qCritical() << "Index of item to replace is not valid!"; return false; } - QList removed_items = parent_item->takeRow (original_index.row ()); - removed_to_parent_map_.insert (removed_items.value(0),parent_item); + QList removed_items = parent_item->takeRow(original_index.row()); + removed_to_parent_map_.insert(removed_items.value(0), parent_item); } - //Insert the new items below the parent item' - foreach (CloudComposerItem* item, new_items) - { - parent_item->appendRow (item); + // Insert the new items below the parent item' + foreach (CloudComposerItem* item, new_items) { + parent_item->appendRow(item); } return true; } ////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -bool -pcl::cloud_composer::CloudCommand::restoreOriginalRemoveNew (const QList & originals, const QList & new_items) -{ - - //Now remove all the new items - foreach (CloudComposerItem* item, new_items) - { - QStandardItem* parent_item = item->parent (); - // If parent is 0, it's parent is invisiblerootitem (That's how Qt defines it... boo!) +bool +pcl::cloud_composer::CloudCommand::restoreOriginalRemoveNew( + const QList& originals, + const QList& new_items) +{ + + // Now remove all the new items + foreach (CloudComposerItem* item, new_items) { + QStandardItem* parent_item = item->parent(); + // If parent is 0, it's parent is invisiblerootitem (That's how Qt defines it... + // boo!) if (parent_item == nullptr) - parent_item = project_model_->invisibleRootItem (); - QPersistentModelIndex to_remove_index = QPersistentModelIndex(project_model_->indexFromItem (item)); - if (!to_remove_index.isValid ()) - { - qCritical () << "Index of item to remove while restoring originals not valid"; + parent_item = project_model_->invisibleRootItem(); + QPersistentModelIndex to_remove_index = + QPersistentModelIndex(project_model_->indexFromItem(item)); + if (!to_remove_index.isValid()) { + qCritical() << "Index of item to remove while restoring originals not valid"; return false; } - //Take them, they're still stored so we don't worry about them - QList removed = parent_item->takeRow (to_remove_index.row ()); - } - //Restore the original items - foreach (const CloudComposerItem* item, originals) - { - //Point iterator to the correct spot - // Find doesn't modify parameter so it should accept a const pointer, but it can't be because it is templated to the map type - // So we hack to get around this with a const cast - const auto& itr = removed_to_parent_map_.find (const_cast (item)); - QStandardItem* parent = itr.value (); - QStandardItem* original = itr.key (); - parent->appendRow (original); - int num = removed_to_parent_map_.remove (original); + // Take them, they're still stored so we don't worry about them + QList removed = parent_item->takeRow(to_remove_index.row()); + } + // Restore the original items + foreach (const CloudComposerItem* item, originals) { + // Point iterator to the correct spot + // Find doesn't modify parameter so it should accept a const pointer, but it can't + // be because it is templated to the map type So we hack to get around this with a + // const cast + const auto& itr = removed_to_parent_map_.find(const_cast(item)); + QStandardItem* parent = itr.value(); + QStandardItem* original = itr.key(); + parent->appendRow(original); + int num = removed_to_parent_map_.remove(original); if (num > 1) - qCritical () << "More than one item with same pointer in removed_to_parent_map_, this is undefined behavior"; - else if (num == 0) - qCritical () << "Could not find key in map to remove, not good!"; + qCritical() << "More than one item with same pointer in removed_to_parent_map_, " + "this is undefined behavior"; + else if (num == 0) + qCritical() << "Could not find key in map to remove, not good!"; } return true; @@ -202,44 +198,42 @@ pcl::cloud_composer::CloudCommand::restoreOriginalRemoveNew (const QList input_data, QUndoCommand* parent) - : CloudCommand (std::move(input_data), parent) -{ - -} +pcl::cloud_composer::ModifyItemCommand::ModifyItemCommand( + QList input_data, QUndoCommand* parent) +: CloudCommand(std::move(input_data), parent) +{} bool -pcl::cloud_composer::ModifyItemCommand::runCommand (AbstractTool* tool) +pcl::cloud_composer::ModifyItemCommand::runCommand(AbstractTool* tool) { - this->setText (tool->getToolName ()); - //For modify item cloud command, each selected item should be processed separately + this->setText(tool->getToolName()); + // For modify item cloud command, each selected item should be processed separately int num_items_returned = 0; - foreach (const CloudComposerItem *item, original_data_) - { - QList input_list; - input_list.append (item); - QList output; + foreach (const CloudComposerItem* item, original_data_) { + QList input_list; + input_list.append(item); + QList output; if (canUseTemplates(input_list)) - output = tool->performAction (input_list, static_cast (template_type_)); + output = tool->performAction( + input_list, static_cast(template_type_)); else - output = tool->performAction (input_list); - if (output.empty ()) - qWarning () << "Warning: Tool " << tool->getToolName () << "returned no item in a ModifyItemCommand"; - else - { + output = tool->performAction(input_list); + if (output.empty()) + qWarning() << "Warning: Tool " << tool->getToolName() + << "returned no item in a ModifyItemCommand"; + else { OutputPair output_pair = {input_list, output}; - output_data_.append (output_pair); + output_data_.append(output_pair); num_items_returned++; } - if (output.size () > 1) - { - qCritical () << "Tool " << tool->getToolName () << "returned multiple items in a ModifyCloudCommand"; + if (output.size() > 1) { + qCritical() << "Tool " << tool->getToolName() + << "returned multiple items in a ModifyCloudCommand"; } - } - if (num_items_returned != original_data_.size ()) - { - qDebug () << "Modify Item command generated "< input_data, QUndoCommand* parent) - : CloudCommand (std::move(input_data), parent) -{ - -} +pcl::cloud_composer::NewItemCloudCommand::NewItemCloudCommand( + QList input_data, QUndoCommand* parent) +: CloudCommand(std::move(input_data), parent) +{} bool -pcl::cloud_composer::NewItemCloudCommand::runCommand (AbstractTool* tool) +pcl::cloud_composer::NewItemCloudCommand::runCommand(AbstractTool* tool) { - this->setText (tool->getToolName ()); - //For new item cloud command, each selected item should be processed separately - //e.g. calculate normals for every selected cloud + this->setText(tool->getToolName()); + // For new item cloud command, each selected item should be processed separately + // e.g. calculate normals for every selected cloud int num_new_items = 0; - foreach (const CloudComposerItem *item, original_data_) - { - QList input_list; - input_list.append (item); - QList output; + foreach (const CloudComposerItem* item, original_data_) { + QList input_list; + input_list.append(item); + QList output; if (canUseTemplates(input_list)) - output = tool->performAction (input_list, static_cast (template_type_)); + output = tool->performAction( + input_list, static_cast(template_type_)); else - output = tool->performAction (input_list); - if (output.empty ()) - qWarning () << "Warning: Tool " << tool->getToolName () << "returned no item in a NewItemCloudCommand"; - else - { + output = tool->performAction(input_list); + if (output.empty()) + qWarning() << "Warning: Tool " << tool->getToolName() + << "returned no item in a NewItemCloudCommand"; + else { OutputPair output_pair = {input_list, output}; - output_data_.append (output_pair); - num_new_items += output.size (); + output_data_.append(output_pair); + num_new_items += output.size(); } - } - if (num_new_items > 0) - { - qDebug () << "New Item command generated "< 0) { + qDebug() << "New Item command generated " << num_new_items << " new items"; return true; } - qWarning () << "New Item command generated no new items!"; + qWarning() << "New Item command generated no new items!"; return false; } ////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void -pcl::cloud_composer::NewItemCloudCommand::undo () +pcl::cloud_composer::NewItemCloudCommand::undo() { last_was_undo_ = true; - qDebug () << "Undo in NewItemCloudCommand"; - foreach (OutputPair output_pair, output_data_) - { - //Each pair can only have one input item, so get it - const CloudComposerItem* const_input_item = output_pair.input_items_.value (0); - QList output_items = output_pair.output_items_; - //Find the input_item index in the project_model_ - QModelIndex input_index = project_model_->indexFromItem (const_input_item); - if (!input_index.isValid ()) - { - qCritical () << "Index of input cloud item is no longer valid, cannot undo NewItemCloudCommand"; + qDebug() << "Undo in NewItemCloudCommand"; + foreach (OutputPair output_pair, output_data_) { + // Each pair can only have one input item, so get it + const CloudComposerItem* const_input_item = output_pair.input_items_.value(0); + QList output_items = output_pair.output_items_; + // Find the input_item index in the project_model_ + QModelIndex input_index = project_model_->indexFromItem(const_input_item); + if (!input_index.isValid()) { + qCritical() << "Index of input cloud item is no longer valid, cannot undo " + "NewItemCloudCommand"; return; } - //Get a copy of the input item we can modify - QStandardItem* item_to_change = project_model_->itemFromIndex (input_index); - //Remove the items we added - foreach (CloudComposerItem* output_item, output_items) - { - QModelIndex output_index = project_model_->indexFromItem (output_item); - item_to_change->takeRow (output_index.row ()); + // Get a copy of the input item we can modify + QStandardItem* item_to_change = project_model_->itemFromIndex(input_index); + // Remove the items we added + foreach (CloudComposerItem* output_item, output_items) { + QModelIndex output_index = project_model_->indexFromItem(output_item); + item_to_change->takeRow(output_index.row()); } - } } ////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void -pcl::cloud_composer::NewItemCloudCommand::redo () +pcl::cloud_composer::NewItemCloudCommand::redo() { last_was_undo_ = false; - qDebug () << "Redo in NewItemCloudCommand - output data size="< output_items = output_pair.output_items_; - //Find the input_item index in the project_model_ - QPersistentModelIndex input_index = QPersistentModelIndex(project_model_->indexFromItem (const_input_item)); - if (!input_index.isValid ()) - { - qCritical () << "Index of input cloud item is no longer valid upon command completion!"; + qDebug() << "Redo in NewItemCloudCommand - output data size=" << output_data_.size(); + foreach (OutputPair output_pair, output_data_) { + // Each pair can only have one input item, so get it + const CloudComposerItem* const_input_item = output_pair.input_items_.value(0); + QList output_items = output_pair.output_items_; + // Find the input_item index in the project_model_ + QPersistentModelIndex input_index = + QPersistentModelIndex(project_model_->indexFromItem(const_input_item)); + if (!input_index.isValid()) { + qCritical() + << "Index of input cloud item is no longer valid upon command completion!"; return; } - //Get a copy of the input item we can modify - QStandardItem* input_item = (project_model_->itemFromIndex (input_index)); - //Append the output items to the input item - foreach (CloudComposerItem* output_item, output_items) - { - input_item->appendRow (output_item); + // Get a copy of the input item we can modify + QStandardItem* input_item = (project_model_->itemFromIndex(input_index)); + // Append the output items to the input item + foreach (CloudComposerItem* output_item, output_items) { + input_item->appendRow(output_item); } } } - ////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -//////////// Split CLOUD COMMAND /////////////////////////////////////////////////////////////////////////// +//////////// Split CLOUD COMMAND +////////////////////////////////////////////////////////////////////////////// -pcl::cloud_composer::SplitCloudCommand::SplitCloudCommand (QList input_data, QUndoCommand* parent) - : CloudCommand (std::move(input_data), parent) -{ - -} +pcl::cloud_composer::SplitCloudCommand::SplitCloudCommand( + QList input_data, QUndoCommand* parent) +: CloudCommand(std::move(input_data), parent) +{} bool -pcl::cloud_composer::SplitCloudCommand::runCommand (AbstractTool* tool) +pcl::cloud_composer::SplitCloudCommand::runCommand(AbstractTool* tool) { - this->setText (tool->getToolName ()); - //For split cloud command, each selected item should be processed separately - //e.g. calculate normals for every selected cloud + this->setText(tool->getToolName()); + // For split cloud command, each selected item should be processed separately + // e.g. calculate normals for every selected cloud int num_new_items = 0; - foreach (const CloudComposerItem *item, original_data_) - { - //Check to see if this is a cloud - QList input_list; - input_list.append (item); - QList output; + foreach (const CloudComposerItem* item, original_data_) { + // Check to see if this is a cloud + QList input_list; + input_list.append(item); + QList output; if (canUseTemplates(input_list)) - output = tool->performAction (input_list, static_cast (template_type_)); + output = tool->performAction( + input_list, static_cast(template_type_)); else - output = tool->performAction (input_list); - if (output.empty ()) - qWarning () << "Warning: Tool " << tool->getToolName () << "returned no item in a SplitCloudCommand"; - else - { - qDebug () << "Split command returned "<performAction(input_list); + if (output.empty()) + qWarning() << "Warning: Tool " << tool->getToolName() + << "returned no item in a SplitCloudCommand"; + else { + qDebug() << "Split command returned " << output.size() << " items"; OutputPair output_pair = {input_list, output}; - output_data_.append (output_pair); - num_new_items += output.size (); + output_data_.append(output_pair); + num_new_items += output.size(); } } - if (num_new_items > 0) - { - qDebug () << "Split Item command generated "< 0) { + qDebug() << "Split Item command generated " << num_new_items << " new items"; return true; } - qWarning () << "Split Item command generated no new items!"; + qWarning() << "Split Item command generated no new items!"; return false; } ////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void -pcl::cloud_composer::SplitCloudCommand::undo () +pcl::cloud_composer::SplitCloudCommand::undo() { last_was_undo_ = true; - qDebug () << "Undo in SplitItemCloudCommand"; - foreach (OutputPair output_pair, output_data_) - { - if (!restoreOriginalRemoveNew (output_pair.input_items_, output_pair.output_items_)) - qCritical () << "Failed to restore old cloud in SplitCloudCommand::undo!"; + qDebug() << "Undo in SplitItemCloudCommand"; + foreach (OutputPair output_pair, output_data_) { + if (!restoreOriginalRemoveNew(output_pair.input_items_, output_pair.output_items_)) + qCritical() << "Failed to restore old cloud in SplitCloudCommand::undo!"; } - } ////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void -pcl::cloud_composer::SplitCloudCommand::redo () +pcl::cloud_composer::SplitCloudCommand::redo() { last_was_undo_ = false; - qDebug () << "Redo in SplitItemCloudCommand - output data size="< input_data, QUndoCommand* parent) - : CloudCommand (std::move(input_data), parent) -{ - -} +pcl::cloud_composer::DeleteItemCommand::DeleteItemCommand( + QList input_data, QUndoCommand* parent) +: CloudCommand(std::move(input_data), parent) +{} bool -pcl::cloud_composer::DeleteItemCommand::runCommand (AbstractTool*) +pcl::cloud_composer::DeleteItemCommand::runCommand(AbstractTool*) { - - //For delete item command, each selected item should be processed separately - //e.g. delete every selected item - foreach (const CloudComposerItem *item, original_data_) - { - QList output; - QList to_delete; - to_delete.append (item); + + // For delete item command, each selected item should be processed separately + // e.g. delete every selected item + foreach (const CloudComposerItem* item, original_data_) { + QList output; + QList to_delete; + to_delete.append(item); OutputPair output_pair = {to_delete, output}; - output_data_.append (output_pair); - this->setText ("Delete "+item->text ()); + output_data_.append(output_pair); + this->setText("Delete " + item->text()); } - if (!original_data_.empty ()) - this->setText ("Delete multiple items"); + if (!original_data_.empty()) + this->setText("Delete multiple items"); return true; } ////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void -pcl::cloud_composer::DeleteItemCommand::undo () +pcl::cloud_composer::DeleteItemCommand::undo() { last_was_undo_ = true; - //Add the original items back into the model - foreach (OutputPair output_pair, output_data_) - { - if (!restoreOriginalRemoveNew (output_pair.input_items_, output_pair.output_items_)) - qCritical () << "Failed to restore items in DeleteItemCommand::undo!"; + // Add the original items back into the model + foreach (OutputPair output_pair, output_data_) { + if (!restoreOriginalRemoveNew(output_pair.input_items_, output_pair.output_items_)) + qCritical() << "Failed to restore items in DeleteItemCommand::undo!"; } } ////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void -pcl::cloud_composer::DeleteItemCommand::redo () +pcl::cloud_composer::DeleteItemCommand::redo() { last_was_undo_ = false; - qDebug () << "Redo in DeleteItemCommand - num items to delete="< output_items; + // In merge command, input clouds will be combined, so send them to tool together + QList output_items; if (canUseTemplates(original_data_)) - output_items = tool->performAction (original_data_, static_cast (template_type_)); + output_items = tool->performAction( + original_data_, static_cast(template_type_)); else - output_items = tool->performAction (original_data_); - MergeSelection* merge_selection = dynamic_cast (tool); - // If this is a merge selection we need to put the partially selected items into the original data list too! - // We didn't send them before because merge selection already knows about them (and needs to tree input list differently from selected items) - if (merge_selection) - { - QList selected_items = merge_selection->getSelectedItems(); + output_items = tool->performAction(original_data_); + MergeSelection* merge_selection = dynamic_cast(tool); + // If this is a merge selection we need to put the partially selected items into the + // original data list too! We didn't send them before because merge selection already + // knows about them (and needs to tree input list differently from selected items) + if (merge_selection) { + QList selected_items = merge_selection->getSelectedItems(); foreach (const CloudItem* item, selected_items) - original_data_.append (item); + original_data_.append(item); } OutputPair output_pair = {original_data_, output_items}; - output_data_.append (output_pair); - - if (output_items.empty ()) - { - qWarning () << "Warning: Tool " << tool->getToolName () << "returned no item in a MergeCloudCommand"; + output_data_.append(output_pair); + + if (output_items.empty()) { + qWarning() << "Warning: Tool " << tool->getToolName() + << "returned no item in a MergeCloudCommand"; return false; } - - this->setText ("Merge Clouds"); + + this->setText("Merge Clouds"); return true; } ////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void -pcl::cloud_composer::MergeCloudCommand::undo () +pcl::cloud_composer::MergeCloudCommand::undo() { last_was_undo_ = true; - //Add the original items back into the model - foreach (OutputPair output_pair, output_data_) - { - if (!restoreOriginalRemoveNew (output_pair.input_items_, output_pair.output_items_)) - qCritical () << "Failed to restore original clouds in MergeCloudCommand::undo!"; + // Add the original items back into the model + foreach (OutputPair output_pair, output_data_) { + if (!restoreOriginalRemoveNew(output_pair.input_items_, output_pair.output_items_)) + qCritical() << "Failed to restore original clouds in MergeCloudCommand::undo!"; } } ////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void -pcl::cloud_composer::MergeCloudCommand::redo () +pcl::cloud_composer::MergeCloudCommand::redo() { - qDebug () << "Redo in MergeCloudCommand "; + qDebug() << "Redo in MergeCloudCommand "; last_was_undo_ = false; - //There is only one output_pair, but that's ok - foreach (OutputPair output_pair, output_data_) - { - //Replace the input with the output for this pair - // This works because all input clouds must have same parent, the root item (clouds must be on top level) - if (! replaceOriginalWithNew (output_pair.input_items_, output_pair.output_items_)) - qCritical () << "Removal of items failed in MergeCloudCommand::redo"; - + // There is only one output_pair, but that's ok + foreach (OutputPair output_pair, output_data_) { + // Replace the input with the output for this pair + // This works because all input clouds must have same parent, the root item (clouds + // must be on top level) + if (!replaceOriginalWithNew(output_pair.input_items_, output_pair.output_items_)) + qCritical() << "Removal of items failed in MergeCloudCommand::redo"; } } - diff --git a/apps/cloud_composer/src/item_inspector.cpp b/apps/cloud_composer/src/item_inspector.cpp index c32914f2..5851c6da 100644 --- a/apps/cloud_composer/src/item_inspector.cpp +++ b/apps/cloud_composer/src/item_inspector.cpp @@ -3,133 +3,121 @@ #include -pcl::cloud_composer::ItemInspector::ItemInspector (QWidget* parent) - : QTabWidget(parent) +pcl::cloud_composer::ItemInspector::ItemInspector(QWidget* parent) : QTabWidget(parent) { current_item_properties_model_ = nullptr; current_project_model_ = nullptr; current_selection_model_ = nullptr; - - parameter_view_ = new QTreeView (); - addTab (parameter_view_, "Parameters"); - + parameter_view_ = new QTreeView(); + addTab(parameter_view_, "Parameters"); } void -pcl::cloud_composer::ItemInspector::setModel (ProjectModel* new_model) +pcl::cloud_composer::ItemInspector::setModel(ProjectModel* new_model) { // DISABLED: JUST KEEP TREES ALWAYS EXPANDED - //If we have a model loaded, save its tree state - //if (current_item_properties_model_) - // storeTreeState (); - QItemSelectionModel* new_selection_model = new_model->getSelectionModel (); + // If we have a model loaded, save its tree state + // if (current_item_properties_model_) + // storeTreeState (); + QItemSelectionModel* new_selection_model = new_model->getSelectionModel(); current_project_model_ = new_model; - - if (current_selection_model_) - { - disconnect (current_selection_model_, SIGNAL (currentChanged (const QModelIndex, const QModelIndex)), - this, SLOT (selectionChanged (const QModelIndex, const QModelIndex))); - removeTabs (); - + + if (current_selection_model_) { + disconnect(current_selection_model_, + SIGNAL(currentChanged(const QModelIndex, const QModelIndex)), + this, + SLOT(selectionChanged(const QModelIndex, const QModelIndex))); + removeTabs(); } current_selection_model_ = new_selection_model; - connect (current_selection_model_, SIGNAL (currentChanged (const QModelIndex, const QModelIndex)), - this, SLOT (selectionChanged (const QModelIndex,const QModelIndex))); - - updateView (); - + connect(current_selection_model_, + SIGNAL(currentChanged(const QModelIndex, const QModelIndex)), + this, + SLOT(selectionChanged(const QModelIndex, const QModelIndex))); + + updateView(); } void -pcl::cloud_composer::ItemInspector::selectionChanged (const QModelIndex &, const QModelIndex &) +pcl::cloud_composer::ItemInspector::selectionChanged(const QModelIndex&, + const QModelIndex&) { - //If we have a model loaded, save its tree state - // if (current_item_properties_model_) - // storeTreeState (); + // If we have a model loaded, save its tree state + // if (current_item_properties_model_) + // storeTreeState (); if (current_project_model_) - updateView (); - + updateView(); } void -pcl::cloud_composer::ItemInspector::storeTreeState () +pcl::cloud_composer::ItemInspector::storeTreeState() { - QList expanded_list; - int row_count = current_item_properties_model_->rowCount (); - for (int i = 0; i < row_count ; ++i) - { - QModelIndex index = current_item_properties_model_->index (i, 0); - if (parameter_view_->isExpanded (index)) - { - expanded_list << QPersistentModelIndex (index); + QList expanded_list; + int row_count = current_item_properties_model_->rowCount(); + for (int i = 0; i < row_count; ++i) { + QModelIndex index = current_item_properties_model_->index(i, 0); + if (parameter_view_->isExpanded(index)) { + expanded_list << QPersistentModelIndex(index); } } // save list - item_treestate_map_.insert (current_item_properties_model_, expanded_list); + item_treestate_map_.insert(current_item_properties_model_, expanded_list); } void -pcl::cloud_composer::ItemInspector::restoreTreeState () +pcl::cloud_composer::ItemInspector::restoreTreeState() { - if (item_treestate_map_.contains (current_item_properties_model_)) - { - parameter_view_->setUpdatesEnabled (false); - - foreach (QPersistentModelIndex item_index, item_treestate_map_.value (current_item_properties_model_)) - { - if (item_index.isValid ()) - parameter_view_->setExpanded (item_index, true); + if (item_treestate_map_.contains(current_item_properties_model_)) { + parameter_view_->setUpdatesEnabled(false); + + foreach (QPersistentModelIndex item_index, + item_treestate_map_.value(current_item_properties_model_)) { + if (item_index.isValid()) + parameter_view_->setExpanded(item_index, true); } - parameter_view_->setUpdatesEnabled (true); + parameter_view_->setUpdatesEnabled(true); } - } -void -pcl::cloud_composer::ItemInspector::itemChanged (QStandardItem *) -{ - - -} +void +pcl::cloud_composer::ItemInspector::itemChanged(QStandardItem*) +{} void -pcl::cloud_composer::ItemInspector::removeTabs () +pcl::cloud_composer::ItemInspector::removeTabs() { - clear (); - addTab (parameter_view_, "Parameters"); + clear(); + addTab(parameter_view_, "Parameters"); } void -pcl::cloud_composer::ItemInspector::updateView () +pcl::cloud_composer::ItemInspector::updateView() { current_item_properties_model_ = nullptr; - QModelIndex current_item = current_selection_model_->currentIndex (); + QModelIndex current_item = current_selection_model_->currentIndex(); const QStandardItemModel* model = nullptr; CloudComposerItem* cloud_item = nullptr; - if (current_item.isValid ()) - model = dynamic_cast (current_item.model ()); - - if (model) - { - cloud_item = dynamic_cast (model->itemFromIndex (current_item)); - if (cloud_item) - { - current_item_properties_model_ = cloud_item->data (ItemDataRole::PROPERTIES).value (); - //Display any additional graphical data if this item has any - QMap tabs = cloud_item->getInspectorTabs (); - foreach (QString tab_name, tabs.keys ()) - { - addTab (tabs.value (tab_name), tab_name); - tabs.value (tab_name)->show (); + if (current_item.isValid()) + model = dynamic_cast(current_item.model()); + + if (model) { + cloud_item = dynamic_cast(model->itemFromIndex(current_item)); + if (cloud_item) { + current_item_properties_model_ = + cloud_item->data(ItemDataRole::PROPERTIES).value(); + // Display any additional graphical data if this item has any + QMap tabs = cloud_item->getInspectorTabs(); + foreach (QString tab_name, tabs.keys()) { + addTab(tabs.value(tab_name), tab_name); + tabs.value(tab_name)->show(); } } } - - - parameter_view_->setModel (current_item_properties_model_); - parameter_view_->resizeColumnToContents (0); + + parameter_view_->setModel(current_item_properties_model_); + parameter_view_->resizeColumnToContents(0); // restoreTreeState (); - parameter_view_->expandAll (); + parameter_view_->expandAll(); } diff --git a/apps/cloud_composer/src/items/cloud_composer_item.cpp b/apps/cloud_composer/src/items/cloud_composer_item.cpp index 2d5c786f..a87d5a2d 100644 --- a/apps/cloud_composer/src/items/cloud_composer_item.cpp +++ b/apps/cloud_composer/src/items/cloud_composer_item.cpp @@ -2,74 +2,74 @@ #include -pcl::cloud_composer::CloudComposerItem::CloudComposerItem (const QString& name) - : QStandardItem(name) +pcl::cloud_composer::CloudComposerItem::CloudComposerItem(const QString& name) +: QStandardItem(name) { - //Set up the properties, store pointer locally for convenience - properties_ = new PropertiesModel (this); - - QString item_id = name + QString ("%1").arg ((long)this); - - - this->setData (QVariant::fromValue (properties_), ItemDataRole::PROPERTIES); - this->setData (QVariant (item_id), ItemDataRole::ITEM_ID); - - this->setForeground (QBrush (Qt::black)); + // Set up the properties, store pointer locally for convenience + properties_ = new PropertiesModel(this); + + QString item_id = name + QString("%1").arg((long)this); + + this->setData(QVariant::fromValue(properties_), ItemDataRole::PROPERTIES); + this->setData(QVariant(item_id), ItemDataRole::ITEM_ID); + + this->setForeground(QBrush(Qt::black)); } -pcl::cloud_composer::CloudComposerItem::~CloudComposerItem () +pcl::cloud_composer::CloudComposerItem::~CloudComposerItem() { - properties_->deleteLater (); + properties_->deleteLater(); } pcl::cloud_composer::CloudComposerItem* -pcl::cloud_composer::CloudComposerItem::clone () const +pcl::cloud_composer::CloudComposerItem::clone() const { - CloudComposerItem* new_item = new CloudComposerItem (this->text ()); - - PropertiesModel* new_item_properties = new_item->getPropertiesModel (); - new_item_properties->copyProperties (properties_); - - return new_item; + CloudComposerItem* new_item = new CloudComposerItem(this->text()); + + PropertiesModel* new_item_properties = new_item->getPropertiesModel(); + new_item_properties->copyProperties(properties_); + + return new_item; } -QList -pcl::cloud_composer::CloudComposerItem::getChildren (CloudComposerItem::ItemType type) const +QList +pcl::cloud_composer::CloudComposerItem::getChildren( + CloudComposerItem::ItemType type) const { - QList items; - for (int i = 0; i < this->rowCount (); ++i) - { - if ( this->child (i)->type () == type ) - { - items.append (dynamic_cast (this->child (i))); + QList items; + for (int i = 0; i < this->rowCount(); ++i) { + if (this->child(i)->type() == type) { + items.append(dynamic_cast(this->child(i))); } } - + return items; } -void -pcl::cloud_composer::CloudComposerItem::addChild (CloudComposerItem *item_arg) +void +pcl::cloud_composer::CloudComposerItem::addChild(CloudComposerItem* item_arg) { - this->appendRow (item_arg); + this->appendRow(item_arg); } void -pcl::cloud_composer::CloudComposerItem::paintView (pcl::visualization::PCLVisualizer::Ptr) const +pcl::cloud_composer::CloudComposerItem::paintView( + pcl::visualization::PCLVisualizer::Ptr) const { - qDebug () << "Paint View in Cloud Composer Item - doing nothing"; + qDebug() << "Paint View in Cloud Composer Item - doing nothing"; } void -pcl::cloud_composer::CloudComposerItem::removeFromView (pcl::visualization::PCLVisualizer::Ptr) const +pcl::cloud_composer::CloudComposerItem::removeFromView( + pcl::visualization::PCLVisualizer::Ptr) const { - qDebug () << "Remove from View in Cloud Composer Item - doing nothing"; + qDebug() << "Remove from View in Cloud Composer Item - doing nothing"; } -QMap -pcl::cloud_composer::CloudComposerItem::getInspectorTabs () +QMap +pcl::cloud_composer::CloudComposerItem::getInspectorTabs() { - return QMap (); + return QMap(); } /* @@ -78,15 +78,13 @@ CloudPtrT pcl::cloud_composer::CloudComposerItem::getCloudPtr () const { QVariant cloud_variant = this->data (CLOUD); - // Get Extract the pointer from the cloud contained in this item, if the type can't be converted, default-constructed value is returned - CloudPtrT ptr; - if (cloud_variant.canConvert ()) - ptr = cloud_variant.value (); + // Get Extract the pointer from the cloud contained in this item, if the type can't be +converted, default-constructed value is returned CloudPtrT ptr; if +(cloud_variant.canConvert ()) ptr = cloud_variant.value (); else - qCritical () << "Requested Cloud of incorrect type from "<text ()<<" correct type is "<text ()<<" correct +type is "< -#include #include -pcl::cloud_composer::FPFHItem::FPFHItem (QString name, const pcl::PointCloud::Ptr& fpfh_ptr, double radius) - : CloudComposerItem (std::move(name)) - , fpfh_ptr_ (fpfh_ptr) - , radius_ (radius) +#include + +pcl::cloud_composer::FPFHItem::FPFHItem( + QString name, + const pcl::PointCloud::Ptr& fpfh_ptr, + double radius) +: CloudComposerItem(std::move(name)), fpfh_ptr_(fpfh_ptr), radius_(radius) { pcl::PointCloud::ConstPtr fpfh_const = fpfh_ptr; - this->setData (QVariant::fromValue (fpfh_const), ItemDataRole::CLOUD_TEMPLATED); - properties_->addCategory ("Core Properties"); - properties_->addProperty ("Radius", QVariant (radius_), Qt::ItemIsEnabled, "Core Properties"); + this->setData(QVariant::fromValue(fpfh_const), ItemDataRole::CLOUD_TEMPLATED); + properties_->addCategory("Core Properties"); + properties_->addProperty( + "Radius", QVariant(radius_), Qt::ItemIsEnabled, "Core Properties"); } pcl::cloud_composer::FPFHItem* -pcl::cloud_composer::FPFHItem::clone () const +pcl::cloud_composer::FPFHItem::clone() const { - pcl::PointCloud::Ptr fpfh_copy (new pcl::PointCloud (*fpfh_ptr_)); - FPFHItem* new_item = new FPFHItem (this->text (), fpfh_copy, radius_); - - PropertiesModel* new_item_properties = new_item->getPropertiesModel (); - new_item_properties->copyProperties (properties_); - - return new_item; + pcl::PointCloud::Ptr fpfh_copy( + new pcl::PointCloud(*fpfh_ptr_)); + FPFHItem* new_item = new FPFHItem(this->text(), fpfh_copy, radius_); + + PropertiesModel* new_item_properties = new_item->getPropertiesModel(); + new_item_properties->copyProperties(properties_); + + return new_item; } -QMap -pcl::cloud_composer::FPFHItem::getInspectorTabs () -{ - //Create the plotter and QVTKWidget if it doesn't exist - if (!plot_) - { - plot_.reset (new pcl::visualization::PCLPlotter); +QMap +pcl::cloud_composer::FPFHItem::getInspectorTabs() +{ + // Create the plotter and QVTKWidget if it doesn't exist + if (!plot_) { + plot_.reset(new pcl::visualization::PCLPlotter); qvtk_ = new PCLQVTKWidget(); - hist_page_ = new QWidget (); - QGridLayout *mainLayout = new QGridLayout (hist_page_); - mainLayout-> addWidget (qvtk_,0,0); + hist_page_ = new QWidget(); + QGridLayout* mainLayout = new QGridLayout(hist_page_); + mainLayout->addWidget(qvtk_, 0, 0); } - //Plot the histogram - plot_->addFeatureHistogram (*fpfh_ptr_, fpfh_ptr_->width, data(ItemDataRole::ITEM_ID).toString().toStdString ()); - //Set the render window of the QVTK widget, update + // Plot the histogram + plot_->addFeatureHistogram(*fpfh_ptr_, + fpfh_ptr_->width, + data(ItemDataRole::ITEM_ID).toString().toStdString()); + // Set the render window of the QVTK widget, update plot_->setViewInteractor(getInteractorCompat(*qvtk_)); setRenderWindowCompat(*qvtk_, *(plot_->getRenderWindow())); #if VTK_MAJOR_VERSION > 8 @@ -50,12 +55,9 @@ pcl::cloud_composer::FPFHItem::getInspectorTabs () #else qvtk_->update(); #endif // VTK_MAJOR_VERSION > 8 - qvtk_->show (); - - - QMap tabs; - tabs.insert ("Histogram",hist_page_); + qvtk_->show(); + + QMap tabs; + tabs.insert("Histogram", hist_page_); return tabs; } - - diff --git a/apps/cloud_composer/src/main.cpp b/apps/cloud_composer/src/main.cpp index 939bad15..d16a6f6a 100644 --- a/apps/cloud_composer/src/main.cpp +++ b/apps/cloud_composer/src/main.cpp @@ -2,12 +2,12 @@ /////////// MAIN //////////////////// int -main (int argc, char ** argv) +main(int argc, char** argv) { // Initialize QT - QApplication app (argc, argv); - + QApplication app(argc, argv); + pcl::cloud_composer::ComposerMainWindow cc; - cc.show (); - return (QApplication::exec ()); + cc.show(); + return (QApplication::exec()); } diff --git a/apps/cloud_composer/src/merge_selection.cpp b/apps/cloud_composer/src/merge_selection.cpp index 63b670f2..9999d9c6 100644 --- a/apps/cloud_composer/src/merge_selection.cpp +++ b/apps/cloud_composer/src/merge_selection.cpp @@ -1,112 +1,110 @@ -#include +#include #include - +#include #include -#include // for pcl::make_shared -#include #include -#include - -pcl::cloud_composer::MergeSelection::MergeSelection (QMap selected_item_index_map, QObject* parent) - : MergeCloudTool (nullptr, parent) - , selected_item_index_map_ (std::move(selected_item_index_map)) -{ +#include // for pcl::make_shared +#include -} +pcl::cloud_composer::MergeSelection::MergeSelection( + QMap selected_item_index_map, + QObject* parent) +: MergeCloudTool(nullptr, parent) +, selected_item_index_map_(std::move(selected_item_index_map)) +{} -QList -pcl::cloud_composer::MergeSelection::performAction (ConstItemList input_data, PointTypeFlags::PointType type) +QList +pcl::cloud_composer::MergeSelection::performAction(ConstItemList input_data, + PointTypeFlags::PointType type) { - if (type != PointTypeFlags::NONE) - { - switch ((std::uint8_t) type) - { - case (PointTypeFlags::XYZ): - return this->performTemplatedAction (input_data); - case (PointTypeFlags::XYZ | PointTypeFlags::RGB): - return this->performTemplatedAction (input_data); - case (PointTypeFlags::XYZ | PointTypeFlags::RGBA): - return this->performTemplatedAction (input_data); + if (type != PointTypeFlags::NONE) { + switch ((std::uint8_t)type) { + case (PointTypeFlags::XYZ): + return this->performTemplatedAction(input_data); + case (PointTypeFlags::XYZ | PointTypeFlags::RGB): + return this->performTemplatedAction(input_data); + case (PointTypeFlags::XYZ | PointTypeFlags::RGBA): + return this->performTemplatedAction(input_data); } } - QList output; + QList output; // Check input data length - if ( input_data.empty () && selected_item_index_map_.isEmpty() ) - { - qCritical () << "Empty input in MergeSelection!"; + if (input_data.empty() && selected_item_index_map_.isEmpty()) { + qCritical() << "Empty input in MergeSelection!"; return output; } - //Make sure all input items are cloud items - foreach (const CloudComposerItem* input_item, input_data) - { - if (input_item->type () != CloudComposerItem::CLOUD_ITEM ) - { - qCritical () << "Input in MergeSelection not valid, contained non-CloudItem input"; + // Make sure all input items are cloud items + foreach (const CloudComposerItem* input_item, input_data) { + if (input_item->type() != CloudComposerItem::CLOUD_ITEM) { + qCritical() << "Input in MergeSelection not valid, contained non-CloudItem input"; return output; } } pcl::ExtractIndices filter; - pcl::PCLPointCloud2::Ptr merged_cloud (new pcl::PCLPointCloud2); - //To Save the pose of the first original item + pcl::PCLPointCloud2::Ptr merged_cloud(new pcl::PCLPointCloud2); + // To Save the pose of the first original item Eigen::Vector4f source_origin; Eigen::Quaternionf source_orientation; bool pose_found = false; - foreach (const CloudItem* input_cloud_item, selected_item_index_map_.keys ()) - { - //If this cloud hasn't been completely selected - if (!input_data.contains (input_cloud_item)) - { - pcl::PCLPointCloud2::ConstPtr input_cloud = input_cloud_item->data (ItemDataRole::CLOUD_BLOB).value (); - qDebug () << "Extracting "<indices.size() << " points out of "<width; - filter.setInputCloud (input_cloud); - filter.setIndices (selected_item_index_map_.value (input_cloud_item)); - pcl::PCLPointCloud2::Ptr original_minus_indices = pcl::make_shared (); - filter.setNegative (true); - filter.filter (*original_minus_indices); - filter.setNegative (false); - pcl::PCLPointCloud2::Ptr selected_points (new pcl::PCLPointCloud2); - filter.filter (*selected_points); + foreach (const CloudItem* input_cloud_item, selected_item_index_map_.keys()) { + // If this cloud hasn't been completely selected + if (!input_data.contains(input_cloud_item)) { + pcl::PCLPointCloud2::ConstPtr input_cloud = + input_cloud_item->data(ItemDataRole::CLOUD_BLOB) + .value(); + qDebug() << "Extracting " + << selected_item_index_map_.value(input_cloud_item)->indices.size() + << " points out of " << input_cloud->width; + filter.setInputCloud(input_cloud); + filter.setIndices(selected_item_index_map_.value(input_cloud_item)); + pcl::PCLPointCloud2::Ptr original_minus_indices = + pcl::make_shared(); + filter.setNegative(true); + filter.filter(*original_minus_indices); + filter.setNegative(false); + pcl::PCLPointCloud2::Ptr selected_points(new pcl::PCLPointCloud2); + filter.filter(*selected_points); - qDebug () << "Original minus indices is "<width; + qDebug() << "Original minus indices is " << original_minus_indices->width; - if (!pose_found) - { - source_origin = input_cloud_item->data (ItemDataRole::ORIGIN).value (); - source_orientation = input_cloud_item->data (ItemDataRole::ORIENTATION).value (); + if (!pose_found) { + source_origin = + input_cloud_item->data(ItemDataRole::ORIGIN).value(); + source_orientation = input_cloud_item->data(ItemDataRole::ORIENTATION) + .value(); pose_found = true; } - CloudItem* new_cloud_item = new CloudItem (input_cloud_item->text () - , original_minus_indices - , source_origin - , source_orientation); - output.append (new_cloud_item); - pcl::PCLPointCloud2::Ptr temp_cloud = pcl::make_shared (); - concatenate (*merged_cloud, *selected_points, *temp_cloud); + CloudItem* new_cloud_item = new CloudItem(input_cloud_item->text(), + original_minus_indices, + source_origin, + source_orientation); + output.append(new_cloud_item); + pcl::PCLPointCloud2::Ptr temp_cloud = pcl::make_shared(); + concatenate(*merged_cloud, *selected_points, *temp_cloud); merged_cloud = temp_cloud; } - //Append the input item to the original list - //input_data.append (input_cloud_item); + // Append the input item to the original list + // input_data.append (input_cloud_item); } - //Just concatenate for all fully selected clouds - foreach (const CloudComposerItem* input_item, input_data) - { - pcl::PCLPointCloud2::ConstPtr input_cloud = input_item->data (ItemDataRole::CLOUD_BLOB).value (); + // Just concatenate for all fully selected clouds + foreach (const CloudComposerItem* input_item, input_data) { + pcl::PCLPointCloud2::ConstPtr input_cloud = + input_item->data(ItemDataRole::CLOUD_BLOB) + .value(); - pcl::PCLPointCloud2::Ptr temp_cloud = pcl::make_shared (); - concatenate (*merged_cloud, *input_cloud, *temp_cloud); + pcl::PCLPointCloud2::Ptr temp_cloud = pcl::make_shared(); + concatenate(*merged_cloud, *input_cloud, *temp_cloud); merged_cloud = temp_cloud; } - CloudItem* cloud_item = new CloudItem ("Cloud from Selection" - , merged_cloud - , source_origin - , source_orientation); + CloudItem* cloud_item = new CloudItem( + "Cloud from Selection", merged_cloud, source_origin, source_orientation); - output.append (cloud_item); + output.append(cloud_item); return output; } diff --git a/apps/cloud_composer/src/point_selectors/click_trackball_interactor_style.cpp b/apps/cloud_composer/src/point_selectors/click_trackball_interactor_style.cpp index 791e0218..96971e09 100644 --- a/apps/cloud_composer/src/point_selectors/click_trackball_interactor_style.cpp +++ b/apps/cloud_composer/src/point_selectors/click_trackball_interactor_style.cpp @@ -4,117 +4,105 @@ #include - #include // For vtkStandardNewMacro #include -namespace pcl -{ - namespace cloud_composer - { - vtkStandardNewMacro(ClickTrackballStyleInteractor); - } +namespace pcl { +namespace cloud_composer { +vtkStandardNewMacro(ClickTrackballStyleInteractor); } +} // namespace pcl -pcl::cloud_composer::ClickTrackballStyleInteractor::ClickTrackballStyleInteractor () +pcl::cloud_composer::ClickTrackballStyleInteractor::ClickTrackballStyleInteractor() { manipulation_complete_event_ = interactor_events::MANIPULATION_COMPLETE_EVENT; - start_matrix_= vtkSmartPointer::New (); - end_matrix_ = vtkSmartPointer::New (); - transform_ = vtkSmartPointer::New (); + start_matrix_ = vtkSmartPointer::New(); + end_matrix_ = vtkSmartPointer::New(); + transform_ = vtkSmartPointer::New(); } void -pcl::cloud_composer::ClickTrackballStyleInteractor::OnLeftButtonDown () +pcl::cloud_composer::ClickTrackballStyleInteractor::OnLeftButtonDown() { vtkInteractorStyleTrackballActor::OnLeftButtonDown(); - + vtkActor* selected_actor = vtkActor::SafeDownCast(this->InteractionProp); if (selected_actor) - selected_actor->GetMatrix (start_matrix_); - + selected_actor->GetMatrix(start_matrix_); } void -pcl::cloud_composer::ClickTrackballStyleInteractor::OnRightButtonDown () +pcl::cloud_composer::ClickTrackballStyleInteractor::OnRightButtonDown() { vtkInteractorStyleTrackballActor::OnRightButtonDown(); - + vtkActor* selected_actor = vtkActor::SafeDownCast(this->InteractionProp); if (selected_actor) - selected_actor->GetMatrix (start_matrix_); - + selected_actor->GetMatrix(start_matrix_); } void -pcl::cloud_composer::ClickTrackballStyleInteractor::OnLeftButtonUp () +pcl::cloud_composer::ClickTrackballStyleInteractor::OnLeftButtonUp() { vtkInteractorStyleTrackballActor::OnLeftButtonUp(); - vtkSmartPointer selected_actor = vtkActor::SafeDownCast(this->InteractionProp); - if (selected_actor) - { - //Fetch the actor we manipulated - - selected_actor->GetMatrix (end_matrix_); + vtkSmartPointer selected_actor = + vtkActor::SafeDownCast(this->InteractionProp); + if (selected_actor) { + // Fetch the actor we manipulated + + selected_actor->GetMatrix(end_matrix_); // Find the id of the actor we manipulated - pcl::visualization::CloudActorMap::const_iterator end = actors_->end (); + pcl::visualization::CloudActorMap::const_iterator end = actors_->end(); QString manipulated_id; - for( pcl::visualization::CloudActorMap::const_iterator itr = actors_->begin (); itr != end; ++itr) - { - //qDebug () << "Id = "<first); - if ( (itr->second).actor == selected_actor) - { - manipulated_id = (QString::fromStdString (itr->first)); - + for (pcl::visualization::CloudActorMap::const_iterator itr = actors_->begin(); + itr != end; + ++itr) { + // qDebug () << "Id = "<first); + if ((itr->second).actor == selected_actor) { + manipulated_id = (QString::fromStdString(itr->first)); } } - if ( !manipulated_id.isEmpty() ) - { - ManipulationEvent* manip_event = new ManipulationEvent (); - manip_event->addManipulation (manipulated_id, start_matrix_, end_matrix_); - this->InvokeEvent (this->manipulation_complete_event_, manip_event); + if (!manipulated_id.isEmpty()) { + ManipulationEvent* manip_event = new ManipulationEvent(); + manip_event->addManipulation(manipulated_id, start_matrix_, end_matrix_); + this->InvokeEvent(this->manipulation_complete_event_, manip_event); } - else - { - qWarning () << "Could not find actor which matches manipulated actor in ClickTrackballStyleInteractor::OnLeftButtonUp!!!"; + else { + qWarning() << "Could not find actor which matches manipulated actor in " + "ClickTrackballStyleInteractor::OnLeftButtonUp!!!"; } } } void -pcl::cloud_composer::ClickTrackballStyleInteractor::OnRightButtonUp () +pcl::cloud_composer::ClickTrackballStyleInteractor::OnRightButtonUp() { vtkInteractorStyleTrackballActor::OnRightButtonUp(); - vtkSmartPointer selected_actor = vtkActor::SafeDownCast(this->InteractionProp); - if (selected_actor) - { - //Fetch the actor we manipulated - - selected_actor->GetMatrix (end_matrix_); + vtkSmartPointer selected_actor = + vtkActor::SafeDownCast(this->InteractionProp); + if (selected_actor) { + // Fetch the actor we manipulated + + selected_actor->GetMatrix(end_matrix_); // Find the id of the actor we manipulated - pcl::visualization::CloudActorMap::const_iterator end = actors_->end (); + pcl::visualization::CloudActorMap::const_iterator end = actors_->end(); QString manipulated_id; - for( pcl::visualization::CloudActorMap::const_iterator itr = actors_->begin (); itr != end; ++itr) - { - //qDebug () << "Id = "<first); - if ( (itr->second).actor == selected_actor) - { - manipulated_id = (QString::fromStdString (itr->first)); - + for (pcl::visualization::CloudActorMap::const_iterator itr = actors_->begin(); + itr != end; + ++itr) { + // qDebug () << "Id = "<first); + if ((itr->second).actor == selected_actor) { + manipulated_id = (QString::fromStdString(itr->first)); } } - if ( !manipulated_id.isEmpty() ) - { - ManipulationEvent* manip_event = new ManipulationEvent (); - manip_event->addManipulation (manipulated_id, start_matrix_, end_matrix_); - this->InvokeEvent (this->manipulation_complete_event_, manip_event); + if (!manipulated_id.isEmpty()) { + ManipulationEvent* manip_event = new ManipulationEvent(); + manip_event->addManipulation(manipulated_id, start_matrix_, end_matrix_); + this->InvokeEvent(this->manipulation_complete_event_, manip_event); } - else - { - qWarning () << "Could not find actor which matches manipulated actor in ClickTrackballStyleInteractor::OnRightButtonUp!!!"; + else { + qWarning() << "Could not find actor which matches manipulated actor in " + "ClickTrackballStyleInteractor::OnRightButtonUp!!!"; } } - } - - diff --git a/apps/cloud_composer/src/point_selectors/interactor_style_switch.cpp b/apps/cloud_composer/src/point_selectors/interactor_style_switch.cpp index 3744a244..a04d2d45 100644 --- a/apps/cloud_composer/src/point_selectors/interactor_style_switch.cpp +++ b/apps/cloud_composer/src/point_selectors/interactor_style_switch.cpp @@ -1,7 +1,7 @@ +#include #include #include #include -#include #include #include @@ -9,118 +9,113 @@ #include #include -namespace pcl -{ - namespace cloud_composer - { - vtkStandardNewMacro(InteractorStyleSwitch); - } +namespace pcl { +namespace cloud_composer { +vtkStandardNewMacro(InteractorStyleSwitch); } +} // namespace pcl -pcl::cloud_composer::InteractorStyleSwitch::InteractorStyleSwitch () +pcl::cloud_composer::InteractorStyleSwitch::InteractorStyleSwitch() { - pcl_vis_style_ = vtkSmartPointer::New (); - name_to_style_map_.insert (interactor_styles::PCL_VISUALIZER, pcl_vis_style_); - - rectangular_frustum_selector_ = vtkSmartPointer::New (); - name_to_style_map_.insert (interactor_styles::RECTANGULAR_FRUSTUM, rectangular_frustum_selector_); - - selected_trackball_interactor_style_ = vtkSmartPointer ::New (); - name_to_style_map_.insert (interactor_styles::SELECTED_TRACKBALL, selected_trackball_interactor_style_); - - click_trackball_interactor_style_ = vtkSmartPointer ::New (); - name_to_style_map_.insert (interactor_styles::CLICK_TRACKBALL, click_trackball_interactor_style_); - + pcl_vis_style_ = + vtkSmartPointer::New(); + name_to_style_map_.insert(interactor_styles::PCL_VISUALIZER, pcl_vis_style_); + + rectangular_frustum_selector_ = vtkSmartPointer::New(); + name_to_style_map_.insert(interactor_styles::RECTANGULAR_FRUSTUM, + rectangular_frustum_selector_); + + selected_trackball_interactor_style_ = + vtkSmartPointer::New(); + name_to_style_map_.insert(interactor_styles::SELECTED_TRACKBALL, + selected_trackball_interactor_style_); + + click_trackball_interactor_style_ = + vtkSmartPointer::New(); + name_to_style_map_.insert(interactor_styles::CLICK_TRACKBALL, + click_trackball_interactor_style_); + area_picker_ = vtkSmartPointer::New(); - point_picker_ = vtkSmartPointer::New (); - + point_picker_ = vtkSmartPointer::New(); + current_style_ = nullptr; - } void -pcl::cloud_composer::InteractorStyleSwitch::initializeInteractorStyles (pcl::visualization::PCLVisualizer::Ptr vis, ProjectModel* model) +pcl::cloud_composer::InteractorStyleSwitch::initializeInteractorStyles( + pcl::visualization::PCLVisualizer::Ptr vis, ProjectModel* model) { - qDebug () << "Initializing Interactor Styles"; + qDebug() << "Initializing Interactor Styles"; vis_ = std::move(vis); project_model_ = model; - - pcl_vis_style_->Initialize (); - rens_ = vis_->getRendererCollection (); - pcl_vis_style_->setRendererCollection (rens_); - pcl_vis_style_->setCloudActorMap (vis_->getCloudActorMap ()); - - rectangular_frustum_selector_->setCloudActorMap (vis_->getCloudActorMap ()); - - selected_trackball_interactor_style_->setCloudActorMap (vis_->getCloudActorMap ()); - selected_trackball_interactor_style_->setProjectModel (project_model_); - - click_trackball_interactor_style_->setCloudActorMap (vis_->getCloudActorMap ()); - click_trackball_interactor_style_->setProjectModel (project_model_); + + pcl_vis_style_->Initialize(); + rens_ = vis_->getRendererCollection(); + pcl_vis_style_->setRendererCollection(rens_); + pcl_vis_style_->setCloudActorMap(vis_->getCloudActorMap()); + + rectangular_frustum_selector_->setCloudActorMap(vis_->getCloudActorMap()); + + selected_trackball_interactor_style_->setCloudActorMap(vis_->getCloudActorMap()); + selected_trackball_interactor_style_->setProjectModel(project_model_); + + click_trackball_interactor_style_->setCloudActorMap(vis_->getCloudActorMap()); + click_trackball_interactor_style_->setProjectModel(project_model_); } void -pcl::cloud_composer::InteractorStyleSwitch::setCurrentInteractorStyle (interactor_styles::INTERACTOR_STYLES interactor_style) +pcl::cloud_composer::InteractorStyleSwitch::setCurrentInteractorStyle( + interactor_styles::INTERACTOR_STYLES interactor_style) { - qDebug () << "Setting interactor style"; - vtkSmartPointer style_ptr = name_to_style_map_.value (interactor_style); + qDebug() << "Setting interactor style"; + vtkSmartPointer style_ptr = + name_to_style_map_.value(interactor_style); if (current_style_) - current_style_->SetInteractor (nullptr); - current_style_= style_ptr; - - if (current_style_) - { - qDebug () << "Modifying current interactor of style!"; - current_style_->SetInteractor (this->Interactor); - current_style_->SetTDxStyle (this->TDxStyle); - - if (interactor_style == interactor_styles::RECTANGULAR_FRUSTUM) - { - vtkInteractorStyleRubberBandPick* rubber_band_style = vtkInteractorStyleRubberBandPick::SafeDownCast (current_style_); - if (rubber_band_style) - { - vis_->getRenderWindow ()->GetInteractor ()->SetPicker (area_picker_); - rubber_band_style->StartSelect (); + current_style_->SetInteractor(nullptr); + current_style_ = style_ptr; + + if (current_style_) { + qDebug() << "Modifying current interactor of style!"; + current_style_->SetInteractor(this->Interactor); + current_style_->SetTDxStyle(this->TDxStyle); + + if (interactor_style == interactor_styles::RECTANGULAR_FRUSTUM) { + vtkInteractorStyleRubberBandPick* rubber_band_style = + vtkInteractorStyleRubberBandPick::SafeDownCast(current_style_); + if (rubber_band_style) { + vis_->getRenderWindow()->GetInteractor()->SetPicker(area_picker_); + rubber_band_style->StartSelect(); } } - - } - - - } //---------------------------------------------------------------------------- -void -pcl::cloud_composer::InteractorStyleSwitch::SetInteractor (vtkRenderWindowInteractor *iren) +void +pcl::cloud_composer::InteractorStyleSwitch::SetInteractor( + vtkRenderWindowInteractor* iren) { - if(iren == this->Interactor) - { + if (iren == this->Interactor) { return; } // if we already have an Interactor then stop observing it - if(this->Interactor) - { + if (this->Interactor) { this->Interactor->RemoveObserver(this->EventCallbackCommand); } this->Interactor = iren; // add observers for each of the events handled in ProcessEvents - if(iren) - { - iren->AddObserver(vtkCommand::CharEvent, - this->EventCallbackCommand, - this->Priority); - - iren->AddObserver(vtkCommand::DeleteEvent, - this->EventCallbackCommand, - this->Priority); + if (iren) { + iren->AddObserver( + vtkCommand::CharEvent, this->EventCallbackCommand, this->Priority); + + iren->AddObserver( + vtkCommand::DeleteEvent, this->EventCallbackCommand, this->Priority); } } //---------------------------------------------------------------------------- -void -pcl::cloud_composer::InteractorStyleSwitch::SetDefaultRenderer (vtkRenderer* renderer) +void +pcl::cloud_composer::InteractorStyleSwitch::SetDefaultRenderer(vtkRenderer* renderer) { vtkInteractorStyle::SetDefaultRenderer(renderer); pcl_vis_style_->SetDefaultRenderer(renderer); @@ -128,8 +123,8 @@ pcl::cloud_composer::InteractorStyleSwitch::SetDefaultRenderer (vtkRenderer* ren } //---------------------------------------------------------------------------- -void -pcl::cloud_composer::InteractorStyleSwitch::SetCurrentRenderer (vtkRenderer* renderer) +void +pcl::cloud_composer::InteractorStyleSwitch::SetCurrentRenderer(vtkRenderer* renderer) { this->vtkInteractorStyle::SetCurrentRenderer(renderer); pcl_vis_style_->SetCurrentRenderer(renderer); @@ -137,7 +132,7 @@ pcl::cloud_composer::InteractorStyleSwitch::SetCurrentRenderer (vtkRenderer* ren } void -pcl::cloud_composer::InteractorStyleSwitch::OnLeave () +pcl::cloud_composer::InteractorStyleSwitch::OnLeave() { - qDebug () << "ON LEAVE"; + qDebug() << "ON LEAVE"; } diff --git a/apps/cloud_composer/src/point_selectors/manipulation_event.cpp b/apps/cloud_composer/src/point_selectors/manipulation_event.cpp index 7c70d738..f416edfb 100644 --- a/apps/cloud_composer/src/point_selectors/manipulation_event.cpp +++ b/apps/cloud_composer/src/point_selectors/manipulation_event.cpp @@ -1,9 +1,11 @@ #include void -pcl::cloud_composer::ManipulationEvent::addManipulation (const QString& id, const vtkSmartPointer& start, const vtkSmartPointer& end) +pcl::cloud_composer::ManipulationEvent::addManipulation( + const QString& id, + const vtkSmartPointer& start, + const vtkSmartPointer& end) { - id_start_map_.insert (id, start); - id_end_map_.insert (id, end); - + id_start_map_.insert(id, start); + id_end_map_.insert(id, end); } diff --git a/apps/cloud_composer/src/point_selectors/rectangular_frustum_selector.cpp b/apps/cloud_composer/src/point_selectors/rectangular_frustum_selector.cpp index 22f0de1c..e1d87ac8 100644 --- a/apps/cloud_composer/src/point_selectors/rectangular_frustum_selector.cpp +++ b/apps/cloud_composer/src/point_selectors/rectangular_frustum_selector.cpp @@ -3,88 +3,99 @@ #include -#include -#include -#include -#include -#include #include +#include +#include +#if VTK_MAJOR_VERSION > 9 || (VTK_MAJOR_VERSION == 9 && VTK_MINOR_VERSION >= 4) +#include +#else +#include +#endif #include +#include +#include +#include -namespace pcl -{ - namespace cloud_composer - { - vtkStandardNewMacro(RectangularFrustumSelector); - } +namespace pcl { +namespace cloud_composer { +vtkStandardNewMacro(RectangularFrustumSelector); } +} // namespace pcl -pcl::cloud_composer::RectangularFrustumSelector::RectangularFrustumSelector () +pcl::cloud_composer::RectangularFrustumSelector::RectangularFrustumSelector() { selection_complete_event_ = interactor_events::SELECTION_COMPLETE_EVENT; } void -pcl::cloud_composer::RectangularFrustumSelector::OnLeftButtonUp () +pcl::cloud_composer::RectangularFrustumSelector::OnLeftButtonUp() { - + vtkSmartPointer selected_actor = vtkSmartPointer::New(); - vtkSmartPointer selected_mapper = vtkSmartPointer::New(); + vtkSmartPointer selected_mapper = + vtkSmartPointer::New(); selected_actor->SetMapper(selected_mapper); - - vtkInteractorStyleRubberBandPick::OnLeftButtonUp (); - - vtkPlanes* frustum = static_cast (this->GetInteractor ()->GetPicker ())->GetFrustum (); - - vtkSmartPointer id_filter = vtkSmartPointer::New (); - id_filter->PointIdsOn (); - - vtkSmartPointer extract_geometry = vtkSmartPointer::New (); - extract_geometry->SetImplicitFunction (frustum); - extract_geometry->SetInputConnection (id_filter->GetOutputPort ()); - - vtkSmartPointer glyph_filter = vtkSmartPointer::New (); - glyph_filter->SetInputConnection (extract_geometry->GetOutputPort ()); - - vtkSmartPointer append = vtkAppendPolyData::New (); - - QMap < QString, vtkPolyData* > id_selected_data_map; - for (const auto &actor : *actors_) - { - const pcl::visualization::CloudActor *act = &actor.second; - vtkMapper* mapper = act->actor->GetMapper (); - vtkDataSet* data = mapper->GetInput (); - vtkPolyData* poly_data = vtkPolyData::SafeDownCast (data); - id_filter->SetInputData (poly_data); - - vtkSmartPointer selected = vtkSmartPointer::New (); - glyph_filter->SetOutput (selected); - glyph_filter->Update (); - if (selected->GetNumberOfPoints() > 0) - { - qDebug () << "Selected " << selected->GetNumberOfPoints () << " points."; - id_selected_data_map.insert ( QString::fromStdString (actor.first), selected); - append->AddInputData (selected); - } + + vtkInteractorStyleRubberBandPick::OnLeftButtonUp(); + + vtkPlanes* frustum = + static_cast(this->GetInteractor()->GetPicker())->GetFrustum(); + +#if VTK_MAJOR_VERSION > 9 || (VTK_MAJOR_VERSION == 9 && VTK_MINOR_VERSION >= 4) + vtkSmartPointer id_filter = vtkSmartPointer::New(); +#else + vtkSmartPointer id_filter = vtkSmartPointer::New(); +#endif + id_filter->PointIdsOn(); + + vtkSmartPointer extract_geometry = + vtkSmartPointer::New(); + extract_geometry->SetImplicitFunction(frustum); + extract_geometry->SetInputConnection(id_filter->GetOutputPort()); + + vtkSmartPointer glyph_filter = + vtkSmartPointer::New(); + glyph_filter->SetInputConnection(extract_geometry->GetOutputPort()); + + vtkSmartPointer append = vtkAppendPolyData::New(); + + QMap id_selected_data_map; + for (const auto& actor : *actors_) { + const pcl::visualization::CloudActor* act = &actor.second; + vtkMapper* mapper = act->actor->GetMapper(); + vtkDataSet* data = mapper->GetInput(); + vtkPolyData* poly_data = vtkPolyData::SafeDownCast(data); + id_filter->SetInputData(poly_data); + + vtkSmartPointer selected = vtkSmartPointer::New(); + glyph_filter->SetOutput(selected); + glyph_filter->Update(); + if (selected->GetNumberOfPoints() > 0) { + qDebug() << "Selected " << selected->GetNumberOfPoints() << " points."; + id_selected_data_map.insert(QString::fromStdString(actor.first), selected); + append->AddInputData(selected); + } } - append->Update (); - vtkSmartPointer all_points = append->GetOutput (); - qDebug () << "Allpoints = " <GetNumberOfPoints (); - - selected_mapper->SetInputData (all_points); - selected_mapper->ScalarVisibilityOff (); - - selected_actor->GetProperty ()->SetColor (0.0, 1.0, 0.0); //(R,G,B) - selected_actor->GetProperty ()->SetPointSize (3); - - this->CurrentRenderer->AddActor (selected_actor); - this->GetInteractor ()->GetRenderWindow ()->Render (); - this->HighlightProp (nullptr); - - if (all_points->GetNumberOfPoints () > 0) - { - SelectionEvent* selected = new SelectionEvent (all_points, selected_actor, selected_mapper, id_selected_data_map, this->CurrentRenderer); - this->InvokeEvent (this->selection_complete_event_, selected); + append->Update(); + vtkSmartPointer all_points = append->GetOutput(); + qDebug() << "Allpoints = " << all_points->GetNumberOfPoints(); + + selected_mapper->SetInputData(all_points); + selected_mapper->ScalarVisibilityOff(); + + selected_actor->GetProperty()->SetColor(0.0, 1.0, 0.0); //(R,G,B) + selected_actor->GetProperty()->SetPointSize(3); + + this->CurrentRenderer->AddActor(selected_actor); + this->GetInteractor()->GetRenderWindow()->Render(); + this->HighlightProp(nullptr); + + if (all_points->GetNumberOfPoints() > 0) { + SelectionEvent* selected = new SelectionEvent(all_points, + selected_actor, + selected_mapper, + id_selected_data_map, + this->CurrentRenderer); + this->InvokeEvent(this->selection_complete_event_, selected); } } - diff --git a/apps/cloud_composer/src/point_selectors/selected_trackball_interactor_style.cpp b/apps/cloud_composer/src/point_selectors/selected_trackball_interactor_style.cpp index 264e5f2f..16fef781 100644 --- a/apps/cloud_composer/src/point_selectors/selected_trackball_interactor_style.cpp +++ b/apps/cloud_composer/src/point_selectors/selected_trackball_interactor_style.cpp @@ -4,124 +4,116 @@ #include #include -#include -#include -#include #include +#include +#include +#include #include +#include #include -#include - -namespace pcl -{ - namespace cloud_composer - { - vtkStandardNewMacro(SelectedTrackballStyleInteractor); - } +namespace pcl { +namespace cloud_composer { +vtkStandardNewMacro(SelectedTrackballStyleInteractor); } +} // namespace pcl -pcl::cloud_composer::SelectedTrackballStyleInteractor::SelectedTrackballStyleInteractor () +pcl::cloud_composer::SelectedTrackballStyleInteractor:: + SelectedTrackballStyleInteractor() { - manipulation_complete_event_ = interactor_events::MANIPULATION_COMPLETE_EVENT; + manipulation_complete_event_ = interactor_events::MANIPULATION_COMPLETE_EVENT; } void -pcl::cloud_composer::SelectedTrackballStyleInteractor::setSelectedActors () +pcl::cloud_composer::SelectedTrackballStyleInteractor::setSelectedActors() { - QList selected_cloud_ids; - QModelIndexList selected_indexes = model_->getSelectionModel()->selectedIndexes (); - foreach (QModelIndex index, selected_indexes) - { - QStandardItem* item = model_->itemFromIndex (index); - CloudItem* cloud_item = dynamic_cast (item); + QList selected_cloud_ids; + QModelIndexList selected_indexes = model_->getSelectionModel()->selectedIndexes(); + foreach (QModelIndex index, selected_indexes) { + QStandardItem* item = model_->itemFromIndex(index); + CloudItem* cloud_item = dynamic_cast(item); if (cloud_item) - selected_cloud_ids.append (cloud_item->getId ()); + selected_cloud_ids.append(cloud_item->getId()); } - - for (const auto &actorItem : *actors_) - { - QString id = QString::fromStdString (actorItem.first); - if (selected_cloud_ids.contains (id)) - { + + for (const auto& actorItem : *actors_) { + QString id = QString::fromStdString(actorItem.first); + if (selected_cloud_ids.contains(id)) { vtkLODActor* actor = actorItem.second.actor; - qDebug () << "Adding "<getId ())) - { - vtkPolyData* points_in_item = id_selected_data_map_.value (cloud_item->getId ()); - vtkIdTypeArray* point_ids = vtkIdTypeArray::SafeDownCast(points_in_item->GetPointData ()->GetArray ("vtkIdFilter_Ids")); - - indices->indices.resize (point_ids->GetNumberOfTuples ()); - for(vtkIdType i =0; i < point_ids->GetNumberOfTuples (); ++i) - { - //qDebug () << "id="<GetValue (i); - indices->indices[i] = point_ids->GetValue (i); + if (id_selected_data_map_.contains(cloud_item->getId())) { + vtkPolyData* points_in_item = id_selected_data_map_.value(cloud_item->getId()); + vtkIdTypeArray* point_ids = vtkIdTypeArray::SafeDownCast( + points_in_item->GetPointData()->GetArray("vtkIdFilter_Ids")); + + indices->indices.resize(point_ids->GetNumberOfTuples()); + for (vtkIdType i = 0; i < point_ids->GetNumberOfTuples(); ++i) { + // qDebug () << "id="<GetValue (i); + indices->indices[i] = point_ids->GetValue(i); } - //qDebug () << points_in_item->GetNumberOfPoints () << " selected points in "<getId (); + // qDebug () << points_in_item->GetNumberOfPoints () << " selected points in + // "<getId (); } - } diff --git a/apps/cloud_composer/src/properties_model.cpp b/apps/cloud_composer/src/properties_model.cpp index 5ac24ddb..b9daf99d 100644 --- a/apps/cloud_composer/src/properties_model.cpp +++ b/apps/cloud_composer/src/properties_model.cpp @@ -1,126 +1,129 @@ -#include #include +#include #include -pcl::cloud_composer::PropertiesModel::PropertiesModel (QObject* parent) - : QStandardItemModel (parent) +pcl::cloud_composer::PropertiesModel::PropertiesModel(QObject* parent) +: QStandardItemModel(parent) { - setHorizontalHeaderItem (0, new QStandardItem ("Name")); - setHorizontalHeaderItem (1, new QStandardItem ("Value")); + setHorizontalHeaderItem(0, new QStandardItem("Name")); + setHorizontalHeaderItem(1, new QStandardItem("Value")); } -pcl::cloud_composer::PropertiesModel::PropertiesModel (CloudComposerItem* parent_item, QObject* parent) - : QStandardItemModel (parent) - , parent_item_ (parent_item) +pcl::cloud_composer::PropertiesModel::PropertiesModel(CloudComposerItem* parent_item, + QObject* parent) +: QStandardItemModel(parent), parent_item_(parent_item) { - setHorizontalHeaderItem (0, new QStandardItem ("Name")); - setHorizontalHeaderItem (1, new QStandardItem ("Value")); - - connect (this, SIGNAL (itemChanged (QStandardItem*)), - this, SLOT (propertyChanged (QStandardItem*))); + setHorizontalHeaderItem(0, new QStandardItem("Name")); + setHorizontalHeaderItem(1, new QStandardItem("Value")); + + connect(this, + SIGNAL(itemChanged(QStandardItem*)), + this, + SLOT(propertyChanged(QStandardItem*))); } -pcl::cloud_composer::PropertiesModel::PropertiesModel (const PropertiesModel& to_copy) -: QStandardItemModel () +pcl::cloud_composer::PropertiesModel::PropertiesModel(const PropertiesModel& to_copy) +: QStandardItemModel() { - for (int i=0; i < to_copy.rowCount (); ++i){ - QList new_row; - QStandardItem* parent = to_copy.item(i,0); - QModelIndex parent_index = to_copy.index(i,0); - new_row.append (parent->clone ()); - for (int j=0; j < to_copy.columnCount (parent_index); ++j) - { - if (to_copy.item (i,j)) - new_row.append (to_copy.item(i,j)->clone ()); + for (int i = 0; i < to_copy.rowCount(); ++i) { + QList new_row; + QStandardItem* parent = to_copy.item(i, 0); + QModelIndex parent_index = to_copy.index(i, 0); + new_row.append(parent->clone()); + for (int j = 0; j < to_copy.columnCount(parent_index); ++j) { + if (to_copy.item(i, j)) + new_row.append(to_copy.item(i, j)->clone()); } - appendRow (new_row); + appendRow(new_row); } } void -pcl::cloud_composer::PropertiesModel::addProperty (const QString& prop_name, const QVariant& value, Qt::ItemFlags flags, const QString& category) +pcl::cloud_composer::PropertiesModel::addProperty(const QString& prop_name, + const QVariant& value, + Qt::ItemFlags flags, + const QString& category) { - QStandardItem* parent_item = invisibleRootItem (); - if (category.size () > 0) - { - QList items = findItems (category); - if (items.empty ()) - qWarning () << "No category named "<text ()<<" adding to root"; - else if (items.size () > 1) - qCritical () << "Multiple categories with same name found!! This is not good..."; + QStandardItem* parent_item = invisibleRootItem(); + if (category.size() > 0) { + QList items = findItems(category); + if (items.empty()) + qWarning() << "No category named " << prop_name << " found in " + << parent_item_->text() << " adding to root"; + else if (items.size() > 1) + qCritical() << "Multiple categories with same name found!! This is not good..."; else - parent_item = items.at (0); + parent_item = items.at(0); } - QList new_row; - QStandardItem* new_property = new QStandardItem (prop_name); - new_property->setFlags (Qt::ItemIsSelectable); - new_row.append (new_property); - - QStandardItem* new_value = new QStandardItem (); - new_value->setFlags (flags); - new_value->setData (value, Qt::EditRole); - new_row.append (new_value); - - parent_item->appendRow (new_row); + QList new_row; + QStandardItem* new_property = new QStandardItem(prop_name); + new_property->setFlags(Qt::ItemIsSelectable); + new_row.append(new_property); + + QStandardItem* new_value = new QStandardItem(); + new_value->setFlags(flags); + new_value->setData(value, Qt::EditRole); + new_row.append(new_value); + + parent_item->appendRow(new_row); } void -pcl::cloud_composer::PropertiesModel::addCategory (const QString& category_name) +pcl::cloud_composer::PropertiesModel::addCategory(const QString& category_name) { - QStandardItem* new_category = new QStandardItem (category_name); - appendRow (new_category); + QStandardItem* new_category = new QStandardItem(category_name); + appendRow(new_category); } -QVariant -pcl::cloud_composer::PropertiesModel::getProperty (const QString& prop_name) const +QVariant +pcl::cloud_composer::PropertiesModel::getProperty(const QString& prop_name) const { - //qDebug () << "Searching for property " << prop_name; - QList items = findItems (prop_name, Qt::MatchExactly | Qt::MatchRecursive, 0); - if (items.empty ()) - { - qWarning () << "No property named "<text (); - return QVariant (); + // qDebug () << "Searching for property " << prop_name; + QList items = + findItems(prop_name, Qt::MatchExactly | Qt::MatchRecursive, 0); + if (items.empty()) { + qWarning() << "No property named " << prop_name << " found in " + << parent_item_->text(); + return QVariant(); } - if (items.size () > 1) - { - qWarning () << "Multiple properties found with name "<text (); + if (items.size() > 1) { + qWarning() << "Multiple properties found with name " << prop_name << " in " + << parent_item_->text(); } - // qDebug () << "Found properties size ="<text()<< " cols ="<columnCount (); - new_row.append (parent->clone ()); - for (int j=1; j < to_copy->columnCount (); ++j) - { - if (to_copy->item (i,j)) - { - new_row.append (to_copy->item(i,j)->clone ()); + for (int i = 0; i < to_copy->rowCount(); ++i) { + QList new_row; + QStandardItem* parent = to_copy->item(i, 0); + qDebug() << "Copying " << parent->text() << " cols =" << to_copy->columnCount(); + new_row.append(parent->clone()); + for (int j = 1; j < to_copy->columnCount(); ++j) { + if (to_copy->item(i, j)) { + new_row.append(to_copy->item(i, j)->clone()); } } - appendRow (new_row); + appendRow(new_row); } } - void -pcl::cloud_composer::PropertiesModel::propertyChanged (QStandardItem*) +pcl::cloud_composer::PropertiesModel::propertyChanged(QStandardItem*) { - //qDebug () << "Property Changed in properties model"; - parent_item_->propertyChanged (); + // qDebug () << "Property Changed in properties model"; + parent_item_->propertyChanged(); } diff --git a/apps/cloud_composer/src/signal_multiplexer.cpp b/apps/cloud_composer/src/signal_multiplexer.cpp index be0506b6..16612f07 100644 --- a/apps/cloud_composer/src/signal_multiplexer.cpp +++ b/apps/cloud_composer/src/signal_multiplexer.cpp @@ -1,15 +1,14 @@ -#include #include +#include -pcl::cloud_composer::SignalMultiplexer::SignalMultiplexer (QObject* parent) - : QObject (parent) -{ - -} - +pcl::cloud_composer::SignalMultiplexer::SignalMultiplexer(QObject* parent) +: QObject(parent) +{} void -pcl::cloud_composer::SignalMultiplexer::connect (QObject* sender, const char* signal, const char* slot) +pcl::cloud_composer::SignalMultiplexer::connect(QObject* sender, + const char* signal, + const char* slot) { Connection conn; conn.sender = sender; @@ -17,12 +16,13 @@ pcl::cloud_composer::SignalMultiplexer::connect (QObject* sender, const char* si conn.slot = slot; connections << conn; - connect (conn); + connect(conn); } - void -pcl::cloud_composer::SignalMultiplexer::connect (const char* signal, QObject* receiver, const char* slot) +pcl::cloud_composer::SignalMultiplexer::connect(const char* signal, + QObject* receiver, + const char* slot) { Connection conn; conn.receiver = receiver; @@ -30,21 +30,20 @@ pcl::cloud_composer::SignalMultiplexer::connect (const char* signal, QObject* re conn.slot = slot; connections << conn; - connect (conn); + connect(conn); } - bool -pcl::cloud_composer::SignalMultiplexer::disconnect (QObject* sender, const char* signal, const char* slot) +pcl::cloud_composer::SignalMultiplexer::disconnect(QObject* sender, + const char* signal, + const char* slot) { - QMutableListIterator it (connections); - while (it.hasNext ()) - { + QMutableListIterator it(connections); + while (it.hasNext()) { Connection conn = it.next(); - if ( (QObject*) conn.sender == sender && - qstrcmp (conn.signal, signal) == 0 && qstrcmp (conn.slot, slot) == 0) - { - disconnect (conn); + if ((QObject*)conn.sender == sender && qstrcmp(conn.signal, signal) == 0 && + qstrcmp(conn.slot, slot) == 0) { + disconnect(conn); it.remove(); return true; } @@ -52,18 +51,17 @@ pcl::cloud_composer::SignalMultiplexer::disconnect (QObject* sender, const char* return false; } - bool -pcl::cloud_composer::SignalMultiplexer::disconnect (const char* signal, QObject* receiver, const char* slot) +pcl::cloud_composer::SignalMultiplexer::disconnect(const char* signal, + QObject* receiver, + const char* slot) { - QMutableListIterator it (connections); - while (it.hasNext ()) - { + QMutableListIterator it(connections); + while (it.hasNext()) { Connection conn = it.next(); - if ( (QObject*) conn.receiver == receiver && - qstrcmp (conn.signal, signal) == 0 && qstrcmp (conn.slot, slot) == 0) - { - disconnect (conn); + if ((QObject*)conn.receiver == receiver && qstrcmp(conn.signal, signal) == 0 && + qstrcmp(conn.slot, slot) == 0) { + disconnect(conn); it.remove(); return true; } @@ -71,9 +69,8 @@ pcl::cloud_composer::SignalMultiplexer::disconnect (const char* signal, QObject* return false; } - void -pcl::cloud_composer::SignalMultiplexer::connect (const Connection& conn) +pcl::cloud_composer::SignalMultiplexer::connect(const Connection& conn) { if (!object) return; @@ -81,14 +78,13 @@ pcl::cloud_composer::SignalMultiplexer::connect (const Connection& conn) return; if (conn.sender) - QObject::connect ( (QObject*) conn.sender, conn.signal, (QObject*) object, conn.slot); + QObject::connect((QObject*)conn.sender, conn.signal, (QObject*)object, conn.slot); else - QObject::connect ( (QObject*) object, conn.signal, (QObject*) conn.receiver, conn.slot); + QObject::connect((QObject*)object, conn.signal, (QObject*)conn.receiver, conn.slot); } - -void -pcl::cloud_composer::SignalMultiplexer::disconnect (const Connection& conn) +void +pcl::cloud_composer::SignalMultiplexer::disconnect(const Connection& conn) { if (!object) return; @@ -96,29 +92,29 @@ pcl::cloud_composer::SignalMultiplexer::disconnect (const Connection& conn) return; if (conn.sender) - QObject::disconnect ( (QObject*) conn.sender, conn.signal, (QObject*) object, conn.slot); + QObject::disconnect( + (QObject*)conn.sender, conn.signal, (QObject*)object, conn.slot); else - QObject::disconnect ( (QObject*) object, conn.signal, (QObject*) conn.receiver, conn.slot); - + QObject::disconnect( + (QObject*)object, conn.signal, (QObject*)conn.receiver, conn.slot); } - -void -pcl::cloud_composer::SignalMultiplexer::setCurrentObject (QObject* newObject) +void +pcl::cloud_composer::SignalMultiplexer::setCurrentObject(QObject* newObject) { if (newObject == object) return; - for (const auto &connection : connections) - disconnect (connection); + for (const auto& connection : connections) + disconnect(connection); object = newObject; - for (const auto &connection : connections) - connect (connection); + for (const auto& connection : connections) + connect(connection); - ProjectModel* model = dynamic_cast (newObject); + ProjectModel* model = dynamic_cast(newObject); if (model) - model->emitAllStateSignals (); - - //let the world know about who's on top now - emit currentObjectChanged (object); + model->emitAllStateSignals(); + + // let the world know about who's on top now + emit currentObjectChanged(object); } diff --git a/apps/cloud_composer/src/tool_interface/abstract_tool.cpp b/apps/cloud_composer/src/tool_interface/abstract_tool.cpp index 8a23d694..21708ef5 100644 --- a/apps/cloud_composer/src/tool_interface/abstract_tool.cpp +++ b/apps/cloud_composer/src/tool_interface/abstract_tool.cpp @@ -1,23 +1,21 @@ #include -pcl::cloud_composer::AbstractTool::AbstractTool (PropertiesModel* parameter_model, QObject* parent) - : QObject (parent) - +pcl::cloud_composer::AbstractTool::AbstractTool(PropertiesModel* parameter_model, + QObject* parent) +: QObject(parent) + { - parameter_model_ = new PropertiesModel (this); - //If there's a model copy it into the local copy - if (parameter_model) - { + parameter_model_ = new PropertiesModel(this); + // If there's a model copy it into the local copy + if (parameter_model) { parameter_model_->copyProperties(parameter_model); - } - - } -QList -pcl::cloud_composer::AbstractTool::performAction (QList , PointTypeFlags::PointType) +QList +pcl::cloud_composer::AbstractTool::performAction(QList, + PointTypeFlags::PointType) { - qDebug () << "AbstractTool::performTemplatedAction"; - return QList (); + qDebug() << "AbstractTool::performTemplatedAction"; + return QList(); } diff --git a/apps/cloud_composer/src/toolbox_model.cpp b/apps/cloud_composer/src/toolbox_model.cpp index dd70fbd2..8e3f70bd 100644 --- a/apps/cloud_composer/src/toolbox_model.cpp +++ b/apps/cloud_composer/src/toolbox_model.cpp @@ -1,247 +1,242 @@ -#include +#include +#include #include #include -#include -#include +#include #include #include -pcl::cloud_composer::ToolBoxModel::ToolBoxModel (QTreeView* tool_view, QTreeView* parameter_view_, QObject* parent) -: QStandardItemModel (parent) -, tool_view_ (tool_view) -, parameter_view_ (parameter_view_) -, project_model_ (nullptr) -{ - -} +pcl::cloud_composer::ToolBoxModel::ToolBoxModel(QTreeView* tool_view, + QTreeView* parameter_view_, + QObject* parent) +: QStandardItemModel(parent) +, tool_view_(tool_view) +, parameter_view_(parameter_view_) +, project_model_(nullptr) +{} -pcl::cloud_composer::ToolBoxModel::ToolBoxModel (const ToolBoxModel&) -: QStandardItemModel () -{ -} +pcl::cloud_composer::ToolBoxModel::ToolBoxModel(const ToolBoxModel&) +: QStandardItemModel() +{} void -pcl::cloud_composer::ToolBoxModel::addTool (ToolFactory* tool_factory) +pcl::cloud_composer::ToolBoxModel::addTool(ToolFactory* tool_factory) { - //qDebug () << "Icon name:"<< tool_factory->getIconName (); - QIcon new_tool_icon = QIcon (tool_factory->getIconName ()); - QStandardItem* new_tool_item = new QStandardItem (new_tool_icon, tool_factory->getPluginName ()); - new_tool_item->setEditable (false); - - new_tool_item->setData (QVariant::fromValue (tool_factory), FACTORY); - PropertiesModel* new_tool_parameters= tool_factory->createToolParameterModel (this); - new_tool_item->setData (QVariant::fromValue (new_tool_parameters), PARAMETER_MODEL); - - tool_items.insert (new_tool_item); - QStandardItem* group_item = addToolGroup (tool_factory->getToolGroupName ()); - group_item->appendRow (new_tool_item); - //Expand the view for this tool group + // qDebug () << "Icon name:"<< tool_factory->getIconName (); + QIcon new_tool_icon = QIcon(tool_factory->getIconName()); + QStandardItem* new_tool_item = + new QStandardItem(new_tool_icon, tool_factory->getPluginName()); + new_tool_item->setEditable(false); + + new_tool_item->setData(QVariant::fromValue(tool_factory), FACTORY); + PropertiesModel* new_tool_parameters = tool_factory->createToolParameterModel(this); + new_tool_item->setData(QVariant::fromValue(new_tool_parameters), PARAMETER_MODEL); + + tool_items.insert(new_tool_item); + QStandardItem* group_item = addToolGroup(tool_factory->getToolGroupName()); + group_item->appendRow(new_tool_item); + // Expand the view for this tool group QModelIndex group_index = this->indexFromItem(group_item); - tool_view_->setExpanded (group_index, true); + tool_view_->setExpanded(group_index, true); } void -pcl::cloud_composer::ToolBoxModel::setSelectionModel (QItemSelectionModel* selection_model) +pcl::cloud_composer::ToolBoxModel::setSelectionModel( + QItemSelectionModel* selection_model) { selection_model_ = selection_model; } - + QStandardItem* -pcl::cloud_composer::ToolBoxModel::addToolGroup (const QString& tool_group_name) +pcl::cloud_composer::ToolBoxModel::addToolGroup(const QString& tool_group_name) { - QList matches_name = findItems (tool_group_name); - if (matches_name.empty ()) - { - QStandardItem* new_group_item = new QStandardItem (tool_group_name); - appendRow (new_group_item); - new_group_item->setSelectable (false); - new_group_item->setEditable (false); + QList matches_name = findItems(tool_group_name); + if (matches_name.empty()) { + QStandardItem* new_group_item = new QStandardItem(tool_group_name); + appendRow(new_group_item); + new_group_item->setSelectable(false); + new_group_item->setEditable(false); return new_group_item; } - if (matches_name.size () > 1) - { - qWarning () << "Multiple tool groups with same name in ToolBoxModel!!"; + if (matches_name.size() > 1) { + qWarning() << "Multiple tool groups with same name in ToolBoxModel!!"; } - - return matches_name.value (0); - + + return matches_name.value(0); } -void -pcl::cloud_composer::ToolBoxModel::activeProjectChanged(ProjectModel* new_model, ProjectModel*) +void +pcl::cloud_composer::ToolBoxModel::activeProjectChanged(ProjectModel* new_model, + ProjectModel*) { - //Disconnect old project model signal for selection change - if (project_model_) - { - disconnect (project_model_->getSelectionModel (), SIGNAL (selectionChanged (QItemSelection,QItemSelection)), - this, SLOT (selectedItemChanged (QItemSelection,QItemSelection))); - disconnect (project_model_, SIGNAL (modelChanged()), - this, SLOT (modelChanged())); - - } - qDebug () << "Active project changed in ToolBox Model!"; - project_model_ = new_model; - - //Update enabled tools, make connection for doing this automatically - if (project_model_) - { - updateEnabledTools (project_model_->getSelectionModel ()->selection ()); - connect (project_model_->getSelectionModel (), SIGNAL (selectionChanged (QItemSelection,QItemSelection)), - this, SLOT (selectedItemChanged (QItemSelection,QItemSelection))); - connect (project_model_, SIGNAL (modelChanged()), - this, SLOT (modelChanged())); + // Disconnect old project model signal for selection change + if (project_model_) { + disconnect(project_model_->getSelectionModel(), + SIGNAL(selectionChanged(QItemSelection, QItemSelection)), + this, + SLOT(selectedItemChanged(QItemSelection, QItemSelection))); + disconnect(project_model_, SIGNAL(modelChanged()), this, SLOT(modelChanged())); } + qDebug() << "Active project changed in ToolBox Model!"; + project_model_ = new_model; + // Update enabled tools, make connection for doing this automatically + if (project_model_) { + updateEnabledTools(project_model_->getSelectionModel()->selection()); + connect(project_model_->getSelectionModel(), + SIGNAL(selectionChanged(QItemSelection, QItemSelection)), + this, + SLOT(selectedItemChanged(QItemSelection, QItemSelection))); + connect(project_model_, SIGNAL(modelChanged()), this, SLOT(modelChanged())); + } } void -pcl::cloud_composer::ToolBoxModel::selectedToolChanged (const QModelIndex & current, const QModelIndex &) +pcl::cloud_composer::ToolBoxModel::selectedToolChanged(const QModelIndex& current, + const QModelIndex&) { - //qDebug() << "Selected Tool changed"; - if (!parameter_view_) - { - qCritical () << "Toolbox parameter view not set!!!"; + // qDebug() << "Selected Tool changed"; + if (!parameter_view_) { + qCritical() << "Toolbox parameter view not set!!!"; return; - } - QVariant parameter_model = current.data (PARAMETER_MODEL); - parameter_view_->setModel ( parameter_model.value ()); - parameter_view_->expandAll (); + } + QVariant parameter_model = current.data(PARAMETER_MODEL); + parameter_view_->setModel(parameter_model.value()); + parameter_view_->expandAll(); } - void -pcl::cloud_composer::ToolBoxModel::toolAction () +pcl::cloud_composer::ToolBoxModel::toolAction() { - QModelIndex current_index = selection_model_->currentIndex (); - if (!current_index.isValid ()) - { - QMessageBox::warning (qobject_cast(this->parent ()), "No Tool Selected", "Cannot execute action, no tool selected!"); + QModelIndex current_index = selection_model_->currentIndex(); + if (!current_index.isValid()) { + QMessageBox::warning(qobject_cast(this->parent()), + "No Tool Selected", + "Cannot execute action, no tool selected!"); return; } - ToolFactory* tool_factory = (current_index.data (FACTORY)).value (); - PropertiesModel* parameter_model = (current_index.data (PARAMETER_MODEL)).value (); + ToolFactory* tool_factory = (current_index.data(FACTORY)).value(); + PropertiesModel* parameter_model = + (current_index.data(PARAMETER_MODEL)).value(); // - AbstractTool* tool = tool_factory->createTool (parameter_model); - - emit enqueueToolAction (tool); + AbstractTool* tool = tool_factory->createTool(parameter_model); + + emit enqueueToolAction(tool); } -void -pcl::cloud_composer::ToolBoxModel::selectedItemChanged ( const QItemSelection & selected, const QItemSelection &) +void +pcl::cloud_composer::ToolBoxModel::selectedItemChanged(const QItemSelection& selected, + const QItemSelection&) { - updateEnabledTools (selected); + updateEnabledTools(selected); } -void -pcl::cloud_composer::ToolBoxModel::enableAllTools () +void +pcl::cloud_composer::ToolBoxModel::enableAllTools() { - foreach (QStandardItem* tool, tool_items) - { - tool->setEnabled (true); + foreach (QStandardItem* tool, tool_items) { + tool->setEnabled(true); } } void -pcl::cloud_composer::ToolBoxModel::modelChanged () +pcl::cloud_composer::ToolBoxModel::modelChanged() { - updateEnabledTools (project_model_->getSelectionModel ()->selection ()); + updateEnabledTools(project_model_->getSelectionModel()->selection()); } void -pcl::cloud_composer::ToolBoxModel::updateEnabledTools (const QItemSelection& current_selection) +pcl::cloud_composer::ToolBoxModel::updateEnabledTools( + const QItemSelection& current_selection) { - //qDebug () << "UPDATING ENABLED TOOLS!"; - QModelIndexList current_indices = current_selection.indexes (); - QMultiMap < int, QStandardItem* > type_items_map; - foreach (QModelIndex current, current_indices) - { - if (current.isValid ()) - { - QStandardItem* current_item = project_model_->itemFromIndex (current); - type_items_map.insert (current_item->type (), current_item); + // qDebug () << "UPDATING ENABLED TOOLS!"; + QModelIndexList current_indices = current_selection.indexes(); + QMultiMap type_items_map; + foreach (QModelIndex current, current_indices) { + if (current.isValid()) { + QStandardItem* current_item = project_model_->itemFromIndex(current); + type_items_map.insert(current_item->type(), current_item); } } - enableAllTools (); - QList enabled_tools = tool_items.values (); - QMap disabled_tools; + enableAllTools(); + QList enabled_tools = tool_items.values(); + QMap disabled_tools; QMutableListIterator enabled_itr(enabled_tools); - //Go through tools, removing from enabled list if they fail to pass tests - while (enabled_itr.hasNext()) - { - QStandardItem* tool_item = enabled_itr.next (); - ToolFactory* tool_factory = (tool_item->data (FACTORY)).value (); - CloudComposerItem::ItemType input_type = tool_factory->getInputItemType (); - QList required_children_types = tool_factory->getRequiredInputChildrenTypes(); - //Check if enough items for tool are selected - if ( tool_factory-> getNumInputItems() > current_indices.size() ) - { - enabled_itr.remove (); - disabled_tools.insert (tool_item, tr("Tool Requires %1 Items (%2 Selected)").arg(tool_factory-> getNumInputItems()).arg(current_indices.size ())); + // Go through tools, removing from enabled list if they fail to pass tests + while (enabled_itr.hasNext()) { + QStandardItem* tool_item = enabled_itr.next(); + ToolFactory* tool_factory = (tool_item->data(FACTORY)).value(); + CloudComposerItem::ItemType input_type = tool_factory->getInputItemType(); + QList required_children_types = + tool_factory->getRequiredInputChildrenTypes(); + // Check if enough items for tool are selected + if (tool_factory->getNumInputItems() > current_indices.size()) { + enabled_itr.remove(); + disabled_tools.insert(tool_item, + tr("Tool Requires %1 Items (%2 Selected)") + .arg(tool_factory->getNumInputItems()) + .arg(current_indices.size())); } - //Check if selection includes at least one item with correct input type - else if ( ! type_items_map.keys ().contains (input_type)) - { - enabled_itr.remove (); - disabled_tools.insert (tool_item, tr("Tool Requires item type %1 selected").arg (ITEM_TYPES_STRINGS.value (input_type - CloudComposerItem::CLOUD_COMPOSER_ITEM))); + // Check if selection includes at least one item with correct input type + else if (!type_items_map.keys().contains(input_type)) { + enabled_itr.remove(); + disabled_tools.insert( + tool_item, + tr("Tool Requires item type %1 selected") + .arg(ITEM_TYPES_STRINGS.value(input_type - + CloudComposerItem::CLOUD_COMPOSER_ITEM))); } - //Check if any of selected items have required children - else if ( !required_children_types.empty ()) - { - QList matching_selected_items = type_items_map.values (input_type); + // Check if any of selected items have required children + else if (!required_children_types.empty()) { + QList matching_selected_items = type_items_map.values(input_type); bool found_valid_items = false; - QList missing_children = required_children_types; - foreach (QStandardItem* item, matching_selected_items) - { - QList found_children_types; - if (!item->hasChildren ()) + QList missing_children = required_children_types; + foreach (QStandardItem* item, matching_selected_items) { + QList found_children_types; + if (!item->hasChildren()) continue; - - //Find types of all children + + // Find types of all children for (int i = 0; i < item->rowCount(); ++i) - found_children_types.append ( static_cast(item->child (i)->type ())); - //Make temporary copy, remove type from it if is present as child - QList req_children_temp = required_children_types; + found_children_types.append( + static_cast(item->child(i)->type())); + // Make temporary copy, remove type from it if is present as child + QList req_children_temp = required_children_types; foreach (CloudComposerItem::ItemType type, found_children_types) - req_children_temp.removeAll (type); - //If temporary is empty, we found all required children - if (req_children_temp.isEmpty ()) - { + req_children_temp.removeAll(type); + // If temporary is empty, we found all required children + if (req_children_temp.isEmpty()) { found_valid_items = true; break; } - //Otherwise, set missing children list - if (req_children_temp.size () < missing_children.size ()) + // Otherwise, set missing children list + if (req_children_temp.size() < missing_children.size()) missing_children = req_children_temp; - - } - //If we didn't find all required children - if (!found_valid_items) - { - enabled_itr.remove (); + // If we didn't find all required children + if (!found_valid_items) { + enabled_itr.remove(); QString missing_children_string; foreach (CloudComposerItem::ItemType type, missing_children) - missing_children_string.append (" "+ITEM_TYPES_STRINGS.value (type - CloudComposerItem::CLOUD_COMPOSER_ITEM)); - disabled_tools.insert (tool_item, tr ("Tool Requires child item of type(s) %1").arg (missing_children_string)); + missing_children_string.append( + " " + + ITEM_TYPES_STRINGS.value(type - CloudComposerItem::CLOUD_COMPOSER_ITEM)); + disabled_tools.insert( + tool_item, + tr("Tool Requires child item of type(s) %1").arg(missing_children_string)); } } } - foreach (QStandardItem* tool, tool_items) - { - if (enabled_tools.contains (tool)) - { - //qDebug () << tool->text() << " is enabled!"; - tool->setToolTip (tool->text() + " is enabled"); + foreach (QStandardItem* tool, tool_items) { + if (enabled_tools.contains(tool)) { + // qDebug () << tool->text() << " is enabled!"; + tool->setToolTip(tool->text() + " is enabled"); } - else - { - // qDebug () << tool->text() << " disabled: "<setToolTip (disabled_tools.value (tool)); - tool->setEnabled (false); + else { + // qDebug () << tool->text() << " disabled: "<setToolTip(disabled_tools.value(tool)); + tool->setEnabled(false); } } - - - } diff --git a/apps/cloud_composer/src/transform_clouds.cpp b/apps/cloud_composer/src/transform_clouds.cpp index 54658e74..cde2459a 100644 --- a/apps/cloud_composer/src/transform_clouds.cpp +++ b/apps/cloud_composer/src/transform_clouds.cpp @@ -1,36 +1,31 @@ -#include +#include #include - +#include #include -#include - -pcl::cloud_composer::TransformClouds::TransformClouds (QMap > transform_map, QObject* parent) - : ModifyItemTool (nullptr, parent) - , transform_map_ (std::move(transform_map)) -{ - -} +pcl::cloud_composer::TransformClouds::TransformClouds( + QMap> transform_map, QObject* parent) +: ModifyItemTool(nullptr, parent), transform_map_(std::move(transform_map)) +{} -QList -pcl::cloud_composer::TransformClouds::performAction (ConstItemList input_data, PointTypeFlags::PointType type) +QList +pcl::cloud_composer::TransformClouds::performAction(ConstItemList input_data, + PointTypeFlags::PointType type) { - if (type != PointTypeFlags::NONE) - { - switch ((std::uint8_t) type) - { - case (PointTypeFlags::XYZ): - return this->performTemplatedAction (input_data); - case (PointTypeFlags::XYZ | PointTypeFlags::RGB): - return this->performTemplatedAction (input_data); - case (PointTypeFlags::XYZ | PointTypeFlags::RGBA): - return this->performTemplatedAction (input_data); + if (type != PointTypeFlags::NONE) { + switch ((std::uint8_t)type) { + case (PointTypeFlags::XYZ): + return this->performTemplatedAction(input_data); + case (PointTypeFlags::XYZ | PointTypeFlags::RGB): + return this->performTemplatedAction(input_data); + case (PointTypeFlags::XYZ | PointTypeFlags::RGBA): + return this->performTemplatedAction(input_data); } } - - QList output; - qCritical () << "Transform requires templated types!"; - + QList output; + + qCritical() << "Transform requires templated types!"; + return output; } diff --git a/apps/cloud_composer/src/work_queue.cpp b/apps/cloud_composer/src/work_queue.cpp index 2d4fb11d..b8662619 100644 --- a/apps/cloud_composer/src/work_queue.cpp +++ b/apps/cloud_composer/src/work_queue.cpp @@ -1,58 +1,45 @@ -#include #include +#include -pcl::cloud_composer::WorkQueue::WorkQueue (QObject* parent) - : QObject (parent) -{ - - - -} +pcl::cloud_composer::WorkQueue::WorkQueue(QObject* parent) : QObject(parent) {} void -pcl::cloud_composer::WorkQueue::enqueueNewAction (AbstractTool* new_tool, ConstItemList input_data) +pcl::cloud_composer::WorkQueue::enqueueNewAction(AbstractTool* new_tool, + ConstItemList input_data) { ActionPair new_action; - //Create a command which will manage data for the tool - new_action.command = new_tool->createCommand (std::move(input_data)); + // Create a command which will manage data for the tool + new_action.command = new_tool->createCommand(std::move(input_data)); new_action.tool = new_tool; - - work_queue_.enqueue (new_action); - checkQueue (); + + work_queue_.enqueue(new_action); + checkQueue(); } void -pcl::cloud_composer::WorkQueue::actionFinished (ActionPair finished_action) +pcl::cloud_composer::WorkQueue::actionFinished(ActionPair finished_action) { - //Signal the project model that the command is done - emit commandComplete (finished_action.command); - - //Queue the tool for deletion - finished_action.tool->deleteLater (); - //Check if there are any remaining commands in queue - checkQueue (); - + // Signal the project model that the command is done + emit commandComplete(finished_action.command); + + // Queue the tool for deletion + finished_action.tool->deleteLater(); + // Check if there are any remaining commands in queue + checkQueue(); } void -pcl::cloud_composer::WorkQueue::checkQueue ( ) +pcl::cloud_composer::WorkQueue::checkQueue() { - if (work_queue_.length () > 0) - { - ActionPair action_to_execute = work_queue_.dequeue (); - if (action_to_execute.command->runCommand (action_to_execute.tool)) - { - //Success, send the command back to the main thread - actionFinished (action_to_execute); + if (work_queue_.length() > 0) { + ActionPair action_to_execute = work_queue_.dequeue(); + if (action_to_execute.command->runCommand(action_to_execute.tool)) { + // Success, send the command back to the main thread + actionFinished(action_to_execute); } - else - { - qDebug () << "FAILED TO EXECUTE COMMAND"; - //Failure, what to do with data?? + else { + qDebug() << "FAILED TO EXECUTE COMMAND"; + // Failure, what to do with data?? } - - } - - } diff --git a/apps/cloud_composer/tools/euclidean_clustering.cpp b/apps/cloud_composer/tools/euclidean_clustering.cpp index fc1a4073..2413544e 100644 --- a/apps/cloud_composer/tools/euclidean_clustering.cpp +++ b/apps/cloud_composer/tools/euclidean_clustering.cpp @@ -1,131 +1,138 @@ -#include #include - -#include // for pcl::make_shared -#include +#include #include #include #include +#include // for pcl::make_shared +#include Q_PLUGIN_METADATA(IID "cloud_composer.ToolFactory/1.0") -pcl::cloud_composer::EuclideanClusteringTool::EuclideanClusteringTool (PropertiesModel* parameter_model, QObject* parent) - : SplitItemTool (parameter_model, parent) -{ - -} +pcl::cloud_composer::EuclideanClusteringTool::EuclideanClusteringTool( + PropertiesModel* parameter_model, QObject* parent) +: SplitItemTool(parameter_model, parent) +{} -QList -pcl::cloud_composer::EuclideanClusteringTool::performAction (ConstItemList input_data, PointTypeFlags::PointType) +QList +pcl::cloud_composer::EuclideanClusteringTool::performAction(ConstItemList input_data, + PointTypeFlags::PointType) { - QList output; + QList output; const CloudComposerItem* input_item; // Check input data length - if ( input_data.empty ()) - { - qCritical () << "Empty input in Euclidean Clustering Tool!"; + if (input_data.empty()) { + qCritical() << "Empty input in Euclidean Clustering Tool!"; return output; } - if ( input_data.size () > 1) - { - qWarning () << "Input vector has more than one item in Euclidean Clustering!"; + if (input_data.size() > 1) { + qWarning() << "Input vector has more than one item in Euclidean Clustering!"; } - input_item = input_data.value (0); + input_item = input_data.value(0); - if (input_item->type () == CloudComposerItem::CLOUD_ITEM) - { - const CloudItem* cloud_item = dynamic_cast (input_item); - if ( cloud_item->isSanitized()) - { - double cluster_tolerance = parameter_model_->getProperty ("Cluster Tolerance").toDouble(); - int min_cluster_size = parameter_model_->getProperty ("Min Cluster Size").toInt(); - int max_cluster_size = parameter_model_->getProperty ("Max Cluster Size").toInt(); + if (input_item->type() == CloudComposerItem::CLOUD_ITEM) { + const CloudItem* cloud_item = dynamic_cast(input_item); + if (cloud_item->isSanitized()) { + double cluster_tolerance = + parameter_model_->getProperty("Cluster Tolerance").toDouble(); + int min_cluster_size = parameter_model_->getProperty("Min Cluster Size").toInt(); + int max_cluster_size = parameter_model_->getProperty("Max Cluster Size").toInt(); - pcl::PCLPointCloud2::ConstPtr input_cloud = input_item->data (ItemDataRole::CLOUD_BLOB).value (); - //Get the cloud in template form - pcl::PointCloud::Ptr cloud (new pcl::PointCloud); - pcl::fromPCLPointCloud2 (*input_cloud, *cloud); + pcl::PCLPointCloud2::ConstPtr input_cloud = + input_item->data(ItemDataRole::CLOUD_BLOB) + .value(); + // Get the cloud in template form + pcl::PointCloud::Ptr cloud(new pcl::PointCloud); + pcl::fromPCLPointCloud2(*input_cloud, *cloud); //////////////// THE WORK - COMPUTING CLUSTERS /////////////////// // Creating the KdTree object for the search method of the extraction - pcl::search::KdTree::Ptr tree (new pcl::search::KdTree); - tree->setInputCloud (cloud); + pcl::search::KdTree::Ptr tree( + new pcl::search::KdTree); + tree->setInputCloud(cloud); std::vector cluster_indices; pcl::EuclideanClusterExtraction ec; - ec.setClusterTolerance (cluster_tolerance); - ec.setMinClusterSize (min_cluster_size); - ec.setMaxClusterSize (max_cluster_size); - ec.setSearchMethod (tree); - ec.setInputCloud (cloud); - ec.extract (cluster_indices); + ec.setClusterTolerance(cluster_tolerance); + ec.setMinClusterSize(min_cluster_size); + ec.setMaxClusterSize(max_cluster_size); + ec.setSearchMethod(tree); + ec.setInputCloud(cloud); + ec.extract(cluster_indices); ////////////////////////////////////////////////////////////////// - //Get copies of the original origin and orientation - Eigen::Vector4f source_origin = input_item->data (ItemDataRole::ORIGIN).value (); - Eigen::Quaternionf source_orientation = input_item->data (ItemDataRole::ORIENTATION).value (); - //Vector to accumulate the extracted indices - pcl::IndicesPtr extracted_indices (new pcl::Indices ()); - //Put found clusters into new cloud_items! - qDebug () << "Found "<data(ItemDataRole::ORIGIN).value(); + Eigen::Quaternionf source_orientation = + input_item->data(ItemDataRole::ORIENTATION).value(); + // Vector to accumulate the extracted indices + pcl::IndicesPtr extracted_indices(new pcl::Indices()); + // Put found clusters into new cloud_items! + qDebug() << "Found " << cluster_indices.size() << " clusters!"; int cluster_count = 0; pcl::ExtractIndices filter; - for (const auto& cluster : cluster_indices) - { - filter.setInputCloud (input_cloud); - // It's annoying that I have to do this, but Euclidean returns a PointIndices struct - pcl::PointIndices::ConstPtr indices_ptr = pcl::make_shared(cluster); - filter.setIndices (indices_ptr); - extracted_indices->insert (extracted_indices->end (), cluster.indices.begin (), cluster.indices.end ()); - //This means remove the other points - filter.setKeepOrganized (false); - pcl::PCLPointCloud2::Ptr cloud_filtered (new pcl::PCLPointCloud2); - filter.filter (*cloud_filtered); + for (const auto& cluster : cluster_indices) { + filter.setInputCloud(input_cloud); + // It's annoying that I have to do this, but Euclidean returns a PointIndices + // struct + pcl::PointIndices::ConstPtr indices_ptr = + pcl::make_shared(cluster); + filter.setIndices(indices_ptr); + extracted_indices->insert( + extracted_indices->end(), cluster.indices.begin(), cluster.indices.end()); + // This means remove the other points + filter.setKeepOrganized(false); + pcl::PCLPointCloud2::Ptr cloud_filtered(new pcl::PCLPointCloud2); + filter.filter(*cloud_filtered); qDebug() << "Cluster has " << cloud_filtered->width << " data points."; - CloudItem* cloud_item = new CloudItem (input_item->text ()+tr("-Clstr %1").arg(cluster_count) - , cloud_filtered - , source_origin - , source_orientation); - output.append (cloud_item); + CloudItem* cloud_item = + new CloudItem(input_item->text() + tr("-Clstr %1").arg(cluster_count), + cloud_filtered, + source_origin, + source_orientation); + output.append(cloud_item); ++cluster_count; } - //We copy input cloud over for special case that no clusters found, since ExtractIndices doesn't work for 0 length vectors - pcl::PCLPointCloud2::Ptr remainder_cloud (new pcl::PCLPointCloud2(*input_cloud)); - if (!cluster_indices.empty ()) - { - //make a cloud containing all the remaining points - filter.setIndices (extracted_indices); - filter.setNegative (true); - filter.filter (*remainder_cloud); + // We copy input cloud over for special case that no clusters found, since + // ExtractIndices doesn't work for 0 length vectors + pcl::PCLPointCloud2::Ptr remainder_cloud(new pcl::PCLPointCloud2(*input_cloud)); + if (!cluster_indices.empty()) { + // make a cloud containing all the remaining points + filter.setIndices(extracted_indices); + filter.setNegative(true); + filter.filter(*remainder_cloud); } - qDebug() << "Cloud has " << remainder_cloud->width << " data points after clusters removed."; - CloudItem* cloud_item = new CloudItem (input_item->text ()+ " unclustered" - , remainder_cloud - , source_origin - , source_orientation); - output.push_front (cloud_item); + qDebug() << "Cloud has " << remainder_cloud->width + << " data points after clusters removed."; + CloudItem* cloud_item = new CloudItem(input_item->text() + " unclustered", + remainder_cloud, + source_origin, + source_orientation); + output.push_front(cloud_item); } else - qCritical () << "Input item in Clustering is not SANITIZED!!!"; + qCritical() << "Input item in Clustering is not SANITIZED!!!"; } - else - { - qCritical () << "Input item in Clustering is not a cloud!!!"; + else { + qCritical() << "Input item in Clustering is not a cloud!!!"; } - return output; } /////////////////// PARAMETER MODEL ///////////////////////////////// pcl::cloud_composer::PropertiesModel* -pcl::cloud_composer::EuclideanClusteringToolFactory::createToolParameterModel (QObject* parent) +pcl::cloud_composer::EuclideanClusteringToolFactory::createToolParameterModel( + QObject* parent) { PropertiesModel* parameter_model = new PropertiesModel(parent); - parameter_model->addProperty ("Cluster Tolerance", 0.02, Qt::ItemIsEditable | Qt::ItemIsEnabled); - parameter_model->addProperty ("Min Cluster Size", 100, Qt::ItemIsEditable | Qt::ItemIsEnabled); - parameter_model->addProperty ("Max Cluster Size", 25000, Qt::ItemIsEditable | Qt::ItemIsEnabled); + parameter_model->addProperty( + "Cluster Tolerance", 0.02, Qt::ItemIsEditable | Qt::ItemIsEnabled); + parameter_model->addProperty( + "Min Cluster Size", 100, Qt::ItemIsEditable | Qt::ItemIsEnabled); + parameter_model->addProperty( + "Max Cluster Size", 25000, Qt::ItemIsEditable | Qt::ItemIsEnabled); return parameter_model; } diff --git a/apps/cloud_composer/tools/fpfh_estimation.cpp b/apps/cloud_composer/tools/fpfh_estimation.cpp index a65056a1..93667545 100644 --- a/apps/cloud_composer/tools/fpfh_estimation.cpp +++ b/apps/cloud_composer/tools/fpfh_estimation.cpp @@ -1,105 +1,107 @@ -#include #include -#include #include - +#include +#include #include -#include #include +#include Q_PLUGIN_METADATA(IID "cloud_composer.ToolFactory/1.0") -pcl::cloud_composer::FPFHEstimationTool::FPFHEstimationTool (PropertiesModel* parameter_model, QObject* parent) - : NewItemTool (parameter_model, parent) -{ +pcl::cloud_composer::FPFHEstimationTool::FPFHEstimationTool( + PropertiesModel* parameter_model, QObject* parent) +: NewItemTool(parameter_model, parent) +{} - -} - -QList -pcl::cloud_composer::FPFHEstimationTool::performAction (ConstItemList input_data, PointTypeFlags::PointType) +QList +pcl::cloud_composer::FPFHEstimationTool::performAction(ConstItemList input_data, + PointTypeFlags::PointType) { - QList output; + QList output; const CloudComposerItem* input_item; // Check input data length - if ( input_data.empty ()) - { - qCritical () << "Empty input in FPFH Estimation Tool!"; + if (input_data.empty()) { + qCritical() << "Empty input in FPFH Estimation Tool!"; return output; } - if ( input_data.size () > 1) - { - qWarning () << "Input vector has more than one item in FPFH Estimation!"; + if (input_data.size() > 1) { + qWarning() << "Input vector has more than one item in FPFH Estimation!"; } - input_item = input_data.value (0); - - - if (input_item->type () == CloudComposerItem::CLOUD_ITEM) - { - //Check if this cloud has normals computed! - QList normals_list = input_item->getChildren (CloudComposerItem::NORMALS_ITEM); - if ( normals_list.empty () ) - { - qCritical () << "No normals item child found in this cloud item"; + input_item = input_data.value(0); + + if (input_item->type() == CloudComposerItem::CLOUD_ITEM) { + // Check if this cloud has normals computed! + QList normals_list = + input_item->getChildren(CloudComposerItem::NORMALS_ITEM); + if (normals_list.empty()) { + qCritical() << "No normals item child found in this cloud item"; return output; } - qDebug () << "Found item text="<text(); + qDebug() << "Found item text=" << normals_list.at(0)->text(); double radius = parameter_model_->getProperty("Radius").toDouble(); - - pcl::PCLPointCloud2::ConstPtr input_cloud = input_item->data (ItemDataRole::CLOUD_BLOB).value (); - //Get the cloud in template form - pcl::PointCloud::Ptr cloud (new pcl::PointCloud); - pcl::fromPCLPointCloud2 (*input_cloud, *cloud); - - //Get the normals cloud, we just use the first normals that were found if there are more than one - pcl::PointCloud::ConstPtr input_normals = normals_list.value(0)->data(ItemDataRole::CLOUD_TEMPLATED).value ::ConstPtr> (); - + + pcl::PCLPointCloud2::ConstPtr input_cloud = + input_item->data(ItemDataRole::CLOUD_BLOB) + .value(); + // Get the cloud in template form + pcl::PointCloud::Ptr cloud(new pcl::PointCloud); + pcl::fromPCLPointCloud2(*input_cloud, *cloud); + + // Get the normals cloud, we just use the first normals that were found if there are + // more than one + pcl::PointCloud::ConstPtr input_normals = + normals_list.value(0) + ->data(ItemDataRole::CLOUD_TEMPLATED) + .value::ConstPtr>(); + pcl::FPFHEstimation fpfh; - // qDebug () << "Input cloud size = "<size (); + // qDebug () << "Input cloud size = "<size (); //////////////// THE WORK - COMPUTING FPFH /////////////////// // Create the FPFH estimation class, and pass the input dataset+normals to it - fpfh.setInputCloud (cloud); - fpfh.setInputNormals (input_normals); + fpfh.setInputCloud(cloud); + fpfh.setInputNormals(input_normals); // Create an empty kdtree representation, and pass it to the FPFH estimation object. - // Its content will be filled inside the object, based on the given input dataset (as no other search surface is given). - qDebug () << "Building KD Tree"; - pcl::search::KdTree::Ptr tree (new pcl::search::KdTree); - fpfh.setSearchMethod (tree); + // Its content will be filled inside the object, based on the given input dataset + // (as no other search surface is given). + qDebug() << "Building KD Tree"; + pcl::search::KdTree::Ptr tree(new pcl::search::KdTree); + fpfh.setSearchMethod(tree); // Output datasets - pcl::PointCloud::Ptr fpfhs (new pcl::PointCloud ()); + pcl::PointCloud::Ptr fpfhs( + new pcl::PointCloud()); // Use all neighbors in a sphere of radius 5cm - // IMPORTANT: the radius used here has to be larger than the radius used to estimate the surface normals!!! - fpfh.setRadiusSearch (radius); + // IMPORTANT: the radius used here has to be larger than the radius used to estimate + // the surface normals!!! + fpfh.setRadiusSearch(radius); // Compute the features - qDebug () << "Computing FPFH features"; - fpfh.compute (*fpfhs); - qDebug () << "Size of computed features ="<width; + qDebug() << "Computing FPFH features"; + fpfh.compute(*fpfhs); + qDebug() << "Size of computed features =" << fpfhs->width; ////////////////////////////////////////////////////////////////// - FPFHItem* fpfh_item = new FPFHItem (tr("FPFH r=%1").arg(radius),fpfhs,radius); - output.append (fpfh_item); + FPFHItem* fpfh_item = new FPFHItem(tr("FPFH r=%1").arg(radius), fpfhs, radius); + output.append(fpfh_item); } - else - { - qCritical () << "Input item in FPFH Estimation is not a cloud!!!"; + else { + qCritical() << "Input item in FPFH Estimation is not a cloud!!!"; } - - + return output; } /////////////////// PARAMETER MODEL ///////////////////////////////// pcl::cloud_composer::PropertiesModel* -pcl::cloud_composer::FPFHEstimationToolFactory::createToolParameterModel (QObject* parent) +pcl::cloud_composer::FPFHEstimationToolFactory::createToolParameterModel( + QObject* parent) { PropertiesModel* parameter_model = new PropertiesModel(parent); - - parameter_model->addProperty ("Radius", 0.03, Qt::ItemIsEditable | Qt::ItemIsEnabled); - + + parameter_model->addProperty("Radius", 0.03, Qt::ItemIsEditable | Qt::ItemIsEnabled); + return parameter_model; } diff --git a/apps/cloud_composer/tools/normal_estimation.cpp b/apps/cloud_composer/tools/normal_estimation.cpp index 55ced5d3..ddef0a39 100644 --- a/apps/cloud_composer/tools/normal_estimation.cpp +++ b/apps/cloud_composer/tools/normal_estimation.cpp @@ -1,83 +1,82 @@ -#include #include - +#include #include #include Q_PLUGIN_METADATA(IID "cloud_composer.ToolFactory/1.0") -pcl::cloud_composer::NormalEstimationTool::NormalEstimationTool (PropertiesModel* parameter_model, QObject* parent) - : NewItemTool (parameter_model, parent) -{ - - -} +pcl::cloud_composer::NormalEstimationTool::NormalEstimationTool( + PropertiesModel* parameter_model, QObject* parent) +: NewItemTool(parameter_model, parent) +{} -QList -pcl::cloud_composer::NormalEstimationTool::performAction (ConstItemList input_data, PointTypeFlags::PointType) +QList +pcl::cloud_composer::NormalEstimationTool::performAction(ConstItemList input_data, + PointTypeFlags::PointType) { - QList output; + QList output; const CloudComposerItem* input_item; // Check input data length - if ( input_data.empty ()) - { - qCritical () << "Empty input in Normal Estimation Tool!"; + if (input_data.empty()) { + qCritical() << "Empty input in Normal Estimation Tool!"; return output; } - if ( input_data.size () > 1) - { - qWarning () << "Input vector has more than one item in Normal Estimation!"; + if (input_data.size() > 1) { + qWarning() << "Input vector has more than one item in Normal Estimation!"; } - input_item = input_data.value (0); - + input_item = input_data.value(0); + pcl::PCLPointCloud2::ConstPtr input_cloud; - if (input_item->type () == CloudComposerItem::CLOUD_ITEM) - { + if (input_item->type() == CloudComposerItem::CLOUD_ITEM) { double radius = parameter_model_->getProperty("Radius").toDouble(); - qDebug () << "Received Radius = " <data (ItemDataRole::CLOUD_BLOB).value (); - qDebug () << "Got cloud size = "<width; + qDebug() << "Received Radius = " << radius; + pcl::PCLPointCloud2::ConstPtr input_cloud = + input_item->data(ItemDataRole::CLOUD_BLOB) + .value(); + qDebug() << "Got cloud size = " << input_cloud->width; //////////////// THE WORK - COMPUTING NORMALS /////////////////// - pcl::PointCloud::Ptr cloud (new pcl::PointCloud); - pcl::fromPCLPointCloud2 (*input_cloud, *cloud); + pcl::PointCloud::Ptr cloud(new pcl::PointCloud); + pcl::fromPCLPointCloud2(*input_cloud, *cloud); // Create the normal estimation class, and pass the input dataset to it pcl::NormalEstimation ne; - ne.setInputCloud (cloud); + ne.setInputCloud(cloud); - // Create an empty kdtree representation, and pass it to the normal estimation object. - // Its content will be filled inside the object, based on the given input dataset (as no other search surface is given). - pcl::search::KdTree::Ptr tree (new pcl::search::KdTree ()); - ne.setSearchMethod (tree); + // Create an empty kdtree representation, and pass it to the normal estimation + // object. Its content will be filled inside the object, based on the given input + // dataset (as no other search surface is given). + pcl::search::KdTree::Ptr tree( + new pcl::search::KdTree()); + ne.setSearchMethod(tree); // Output datasets - pcl::PointCloud::Ptr cloud_normals (new pcl::PointCloud); + pcl::PointCloud::Ptr cloud_normals(new pcl::PointCloud); // Use all neighbors in a sphere of radius 3cm - ne.setRadiusSearch (radius); + ne.setRadiusSearch(radius); // Compute the features - ne.compute (*cloud_normals); + ne.compute(*cloud_normals); ////////////////////////////////////////////////////////////////// - NormalsItem* normals_item = new NormalsItem (tr("Normals r=%1").arg(radius),cloud_normals,radius); - output.append (normals_item); - qDebug () << "Calced normals"; + NormalsItem* normals_item = + new NormalsItem(tr("Normals r=%1").arg(radius), cloud_normals, radius); + output.append(normals_item); + qDebug() << "Calced normals"; } - else - { - qDebug () << "Input item in Normal Estimation is not a cloud!!!"; + else { + qDebug() << "Input item in Normal Estimation is not a cloud!!!"; } - - + return output; } /////////////////// PARAMETER MODEL ///////////////////////////////// pcl::cloud_composer::PropertiesModel* -pcl::cloud_composer::NormalEstimationToolFactory::createToolParameterModel (QObject* parent) +pcl::cloud_composer::NormalEstimationToolFactory::createToolParameterModel( + QObject* parent) { PropertiesModel* parameter_model = new PropertiesModel(parent); - - parameter_model->addProperty ("Radius", 0.04, Qt::ItemIsEditable | Qt::ItemIsEnabled); - + + parameter_model->addProperty("Radius", 0.04, Qt::ItemIsEditable | Qt::ItemIsEnabled); + return parameter_model; } diff --git a/apps/cloud_composer/tools/organized_segmentation.cpp b/apps/cloud_composer/tools/organized_segmentation.cpp index 47d7430f..73679e87 100644 --- a/apps/cloud_composer/tools/organized_segmentation.cpp +++ b/apps/cloud_composer/tools/organized_segmentation.cpp @@ -1,58 +1,59 @@ -#include #include - -#include +#include +#include #include #include #include - - -#include +#include Q_PLUGIN_METADATA(IID "cloud_composer.ToolFactory/1.0") -pcl::cloud_composer::OrganizedSegmentationTool::OrganizedSegmentationTool (PropertiesModel* parameter_model, QObject* parent) -: SplitItemTool (parameter_model, parent) -{ - -} +pcl::cloud_composer::OrganizedSegmentationTool::OrganizedSegmentationTool( + PropertiesModel* parameter_model, QObject* parent) +: SplitItemTool(parameter_model, parent) +{} -QList -pcl::cloud_composer::OrganizedSegmentationTool::performAction (ConstItemList input_data, PointTypeFlags::PointType type) +QList +pcl::cloud_composer::OrganizedSegmentationTool::performAction( + ConstItemList input_data, PointTypeFlags::PointType type) { - if (type != PointTypeFlags::NONE) - { - switch ((std::uint8_t) type) - { - case (PointTypeFlags::XYZ): - return this->performTemplatedAction (input_data); - case (PointTypeFlags::XYZ | PointTypeFlags::RGB): - return this->performTemplatedAction (input_data); - case (PointTypeFlags::XYZ | PointTypeFlags::RGBA): - return this->performTemplatedAction (input_data); + if (type != PointTypeFlags::NONE) { + switch ((std::uint8_t)type) { + case (PointTypeFlags::XYZ): + return this->performTemplatedAction(input_data); + case (PointTypeFlags::XYZ | PointTypeFlags::RGB): + return this->performTemplatedAction(input_data); + case (PointTypeFlags::XYZ | PointTypeFlags::RGBA): + return this->performTemplatedAction(input_data); } } - - QList output; - - qCritical () << "organized_segmentation requires templated types!"; - + + QList output; + + qCritical() << "organized_segmentation requires templated types!"; + return output; -} +} /////////////////// PARAMETER MODEL ///////////////////////////////// pcl::cloud_composer::PropertiesModel* -pcl::cloud_composer::OrganizedSegmentationToolFactory::createToolParameterModel (QObject* parent) +pcl::cloud_composer::OrganizedSegmentationToolFactory::createToolParameterModel( + QObject* parent) { PropertiesModel* parameter_model = new PropertiesModel(parent); - - parameter_model->addProperty ("Min Inliers", 1000, Qt::ItemIsEditable | Qt::ItemIsEnabled); - parameter_model->addProperty ("Min Plane Size", 10000, Qt::ItemIsEditable | Qt::ItemIsEnabled); - parameter_model->addProperty ("Angular Threshold", 2.0, Qt::ItemIsEditable | Qt::ItemIsEnabled); - parameter_model->addProperty ("Distance Threshold", 0.02, Qt::ItemIsEditable | Qt::ItemIsEnabled); - parameter_model->addProperty ("Cluster Dist. Thresh.", 0.01, Qt::ItemIsEditable | Qt::ItemIsEnabled); - parameter_model->addProperty ("Min Cluster Size", 1000, Qt::ItemIsEditable | Qt::ItemIsEnabled); - - + + parameter_model->addProperty( + "Min Inliers", 1000, Qt::ItemIsEditable | Qt::ItemIsEnabled); + parameter_model->addProperty( + "Min Plane Size", 10000, Qt::ItemIsEditable | Qt::ItemIsEnabled); + parameter_model->addProperty( + "Angular Threshold", 2.0, Qt::ItemIsEditable | Qt::ItemIsEnabled); + parameter_model->addProperty( + "Distance Threshold", 0.02, Qt::ItemIsEditable | Qt::ItemIsEnabled); + parameter_model->addProperty( + "Cluster Dist. Thresh.", 0.01, Qt::ItemIsEditable | Qt::ItemIsEnabled); + parameter_model->addProperty( + "Min Cluster Size", 1000, Qt::ItemIsEditable | Qt::ItemIsEnabled); + return parameter_model; } diff --git a/apps/cloud_composer/tools/sanitize_cloud.cpp b/apps/cloud_composer/tools/sanitize_cloud.cpp index d56d5276..90d37195 100644 --- a/apps/cloud_composer/tools/sanitize_cloud.cpp +++ b/apps/cloud_composer/tools/sanitize_cloud.cpp @@ -1,75 +1,75 @@ -#include #include +#include #include -#include // for pcl::make_shared +#include // for pcl::make_shared Q_PLUGIN_METADATA(IID "cloud_composer.ToolFactory/1.0") -pcl::cloud_composer::SanitizeCloudTool::SanitizeCloudTool (PropertiesModel* parameter_model, QObject* parent) -: ModifyItemTool (parameter_model, parent) -{ -} +pcl::cloud_composer::SanitizeCloudTool::SanitizeCloudTool( + PropertiesModel* parameter_model, QObject* parent) +: ModifyItemTool(parameter_model, parent) +{} -QList -pcl::cloud_composer::SanitizeCloudTool::performAction (ConstItemList input_data, PointTypeFlags::PointType) +QList +pcl::cloud_composer::SanitizeCloudTool::performAction(ConstItemList input_data, + PointTypeFlags::PointType) { - QList output; + QList output; const CloudComposerItem* input_item; // Check input data length - if ( input_data.empty ()) - { - qCritical () << "Empty input in SanitizeCloudTool!"; + if (input_data.empty()) { + qCritical() << "Empty input in SanitizeCloudTool!"; return output; } - input_item = input_data.value (0); - - if (input_item->type () == CloudComposerItem::CLOUD_ITEM ) - { - pcl::PCLPointCloud2::ConstPtr input_cloud = input_item->data (ItemDataRole::CLOUD_BLOB).value (); - - bool keep_organized = parameter_model_->getProperty("Keep Organized").toBool (); - + input_item = input_data.value(0); + + if (input_item->type() == CloudComposerItem::CLOUD_ITEM) { + pcl::PCLPointCloud2::ConstPtr input_cloud = + input_item->data(ItemDataRole::CLOUD_BLOB) + .value(); + + bool keep_organized = parameter_model_->getProperty("Keep Organized").toBool(); + //////////////// THE WORK - FILTERING NANS /////////////////// // Create the filtering object pcl::PassThrough pass_filter; - pass_filter.setInputCloud (input_cloud); - pass_filter.setKeepOrganized (keep_organized); - - //Create output cloud - pcl::PCLPointCloud2::Ptr cloud_filtered = pcl::make_shared (); - //Filter! - pass_filter.filter (*cloud_filtered); - + pass_filter.setInputCloud(input_cloud); + pass_filter.setKeepOrganized(keep_organized); + + // Create output cloud + pcl::PCLPointCloud2::Ptr cloud_filtered = pcl::make_shared(); + // Filter! + pass_filter.filter(*cloud_filtered); + ////////////////////////////////////////////////////////////////// - //Get copies of the original origin and orientation - Eigen::Vector4f source_origin = input_item->data (ItemDataRole::ORIGIN).value (); - Eigen::Quaternionf source_orientation = input_item->data (ItemDataRole::ORIENTATION).value (); - //Put the modified cloud into an item, stick in output - CloudItem* cloud_item = new CloudItem (input_item->text () + tr (" sanitized") - , cloud_filtered - , source_origin - , source_orientation); - - - output.append (cloud_item); + // Get copies of the original origin and orientation + Eigen::Vector4f source_origin = + input_item->data(ItemDataRole::ORIGIN).value(); + Eigen::Quaternionf source_orientation = + input_item->data(ItemDataRole::ORIENTATION).value(); + // Put the modified cloud into an item, stick in output + CloudItem* cloud_item = new CloudItem(input_item->text() + tr(" sanitized"), + cloud_filtered, + source_origin, + source_orientation); + + output.append(cloud_item); } - else - { - qDebug () << "Input item in StatisticalOutlierRemovalTool is not a cloud!!!"; + else { + qDebug() << "Input item in StatisticalOutlierRemovalTool is not a cloud!!!"; } - - + return output; } /////////////////// PARAMETER MODEL ///////////////////////////////// pcl::cloud_composer::PropertiesModel* -pcl::cloud_composer::SanitizeCloudToolFactory::createToolParameterModel (QObject* parent) +pcl::cloud_composer::SanitizeCloudToolFactory::createToolParameterModel(QObject* parent) { PropertiesModel* parameter_model = new PropertiesModel(parent); - - parameter_model->addProperty ("Keep Organized", false, Qt::ItemIsEditable | Qt::ItemIsEnabled); - + + parameter_model->addProperty( + "Keep Organized", false, Qt::ItemIsEditable | Qt::ItemIsEnabled); + return parameter_model; } - diff --git a/apps/cloud_composer/tools/statistical_outlier_removal.cpp b/apps/cloud_composer/tools/statistical_outlier_removal.cpp index 3213a975..d6742601 100644 --- a/apps/cloud_composer/tools/statistical_outlier_removal.cpp +++ b/apps/cloud_composer/tools/statistical_outlier_removal.cpp @@ -1,89 +1,87 @@ -#include #include - +#include #include #include Q_PLUGIN_METADATA(IID "cloud_composer.ToolFactory/1.0") -pcl::cloud_composer::StatisticalOutlierRemovalTool::StatisticalOutlierRemovalTool (PropertiesModel* parameter_model, QObject* parent) - : ModifyItemTool (parameter_model, parent) -{ +pcl::cloud_composer::StatisticalOutlierRemovalTool::StatisticalOutlierRemovalTool( + PropertiesModel* parameter_model, QObject* parent) +: ModifyItemTool(parameter_model, parent) +{} - -} - -QList -pcl::cloud_composer::StatisticalOutlierRemovalTool::performAction (ConstItemList input_data, PointTypeFlags::PointType) +QList +pcl::cloud_composer::StatisticalOutlierRemovalTool::performAction( + ConstItemList input_data, PointTypeFlags::PointType) { - QList output; + QList output; const CloudComposerItem* input_item; // Check input data length - if ( input_data.empty ()) - { - qCritical () << "Empty input in StatisticalOutlierRemovalTool!"; + if (input_data.empty()) { + qCritical() << "Empty input in StatisticalOutlierRemovalTool!"; return output; } - if ( input_data.size () > 1) - { - qWarning () << "Input vector has more than one item in StatisticalOutlierRemovalTool"; + if (input_data.size() > 1) { + qWarning() + << "Input vector has more than one item in StatisticalOutlierRemovalTool"; } - input_item = input_data.value (0); - if ( !input_item->isSanitized () ) - { - qCritical () << "StatisticalOutlierRemovalTool requires sanitized input!"; + input_item = input_data.value(0); + if (!input_item->isSanitized()) { + qCritical() << "StatisticalOutlierRemovalTool requires sanitized input!"; return output; } - - if (input_item->type () == CloudComposerItem::CLOUD_ITEM ) - { - pcl::PCLPointCloud2::ConstPtr input_cloud = input_item->data (ItemDataRole::CLOUD_BLOB).value (); - - int mean_k = parameter_model_->getProperty("Mean K").toInt (); - double std_dev_thresh = parameter_model_->getProperty ("Std Dev Thresh").toDouble (); - + + if (input_item->type() == CloudComposerItem::CLOUD_ITEM) { + pcl::PCLPointCloud2::ConstPtr input_cloud = + input_item->data(ItemDataRole::CLOUD_BLOB) + .value(); + + int mean_k = parameter_model_->getProperty("Mean K").toInt(); + double std_dev_thresh = parameter_model_->getProperty("Std Dev Thresh").toDouble(); + //////////////// THE WORK - FILTERING OUTLIERS /////////////////// // Create the filtering object pcl::StatisticalOutlierRemoval sor; - sor.setInputCloud (input_cloud); - sor.setMeanK (mean_k); - sor.setStddevMulThresh (std_dev_thresh); - - //Create output cloud - pcl::PCLPointCloud2::Ptr cloud_filtered (new pcl::PCLPointCloud2); - //Filter! - sor.filter (*cloud_filtered); + sor.setInputCloud(input_cloud); + sor.setMeanK(mean_k); + sor.setStddevMulThresh(std_dev_thresh); + + // Create output cloud + pcl::PCLPointCloud2::Ptr cloud_filtered(new pcl::PCLPointCloud2); + // Filter! + sor.filter(*cloud_filtered); ////////////////////////////////////////////////////////////////// - //Get copies of the original origin and orientation - Eigen::Vector4f source_origin = input_item->data (ItemDataRole::ORIGIN).value (); - Eigen::Quaternionf source_orientation = input_item->data (ItemDataRole::ORIENTATION).value (); - //Put the modified cloud into an item, stick in output - CloudItem* cloud_item = new CloudItem (input_item->text () + tr (" sor filtered") - , cloud_filtered - , source_origin - , source_orientation); + // Get copies of the original origin and orientation + Eigen::Vector4f source_origin = + input_item->data(ItemDataRole::ORIGIN).value(); + Eigen::Quaternionf source_orientation = + input_item->data(ItemDataRole::ORIENTATION).value(); + // Put the modified cloud into an item, stick in output + CloudItem* cloud_item = new CloudItem(input_item->text() + tr(" sor filtered"), + cloud_filtered, + source_origin, + source_orientation); - - output.append (cloud_item); + output.append(cloud_item); } - else - { - qDebug () << "Input item in StatisticalOutlierRemovalTool is not a cloud!!!"; + else { + qDebug() << "Input item in StatisticalOutlierRemovalTool is not a cloud!!!"; } - - + return output; } /////////////////// PARAMETER MODEL ///////////////////////////////// pcl::cloud_composer::PropertiesModel* -pcl::cloud_composer::StatisticalOutlierRemovalToolFactory::createToolParameterModel (QObject* parent) +pcl::cloud_composer::StatisticalOutlierRemovalToolFactory::createToolParameterModel( + QObject* parent) { PropertiesModel* parameter_model = new PropertiesModel(parent); - - parameter_model->addProperty ("Mean K", 50, Qt::ItemIsEditable | Qt::ItemIsEnabled); - parameter_model->addProperty ("Std Dev Thresh", 1.0, Qt::ItemIsEditable | Qt::ItemIsEnabled); - + + parameter_model->addProperty("Mean K", 50, Qt::ItemIsEditable | Qt::ItemIsEnabled); + parameter_model->addProperty( + "Std Dev Thresh", 1.0, Qt::ItemIsEditable | Qt::ItemIsEnabled); + return parameter_model; } diff --git a/apps/cloud_composer/tools/supervoxels.cpp b/apps/cloud_composer/tools/supervoxels.cpp index 6c22b37f..853a32e2 100644 --- a/apps/cloud_composer/tools/supervoxels.cpp +++ b/apps/cloud_composer/tools/supervoxels.cpp @@ -1,56 +1,61 @@ -#include #include +#include +#include #include #include -#include #include - -#include +#include Q_PLUGIN_METADATA(IID "cloud_composer.ToolFactory/1.0") -pcl::cloud_composer::SupervoxelsTool::SupervoxelsTool (PropertiesModel* parameter_model, QObject* parent) -: SplitItemTool (parameter_model, parent) -{ - -} +pcl::cloud_composer::SupervoxelsTool::SupervoxelsTool(PropertiesModel* parameter_model, + QObject* parent) +: SplitItemTool(parameter_model, parent) +{} -QList -pcl::cloud_composer::SupervoxelsTool::performAction (ConstItemList input_data, PointTypeFlags::PointType type) +QList +pcl::cloud_composer::SupervoxelsTool::performAction(ConstItemList input_data, + PointTypeFlags::PointType type) { - if (type != PointTypeFlags::NONE) - { - switch ((std::uint8_t) type) - { - case (PointTypeFlags::XYZ | PointTypeFlags::RGB): - return this->performTemplatedAction (input_data); - case (PointTypeFlags::XYZ | PointTypeFlags::RGBA): - return this->performTemplatedAction (input_data); + if (type != PointTypeFlags::NONE) { + switch ((std::uint8_t)type) { + case (PointTypeFlags::XYZ | PointTypeFlags::RGB): + return this->performTemplatedAction(input_data); + case (PointTypeFlags::XYZ | PointTypeFlags::RGBA): + return this->performTemplatedAction(input_data); } } - - QList output; - - qCritical () << "supervoxels requires templated types!"; - - return output; -} -template QList pcl::cloud_composer::SupervoxelsTool::performTemplatedAction (const QList &); -//template QList pcl::cloud_composer::SupervoxelsTool::performTemplatedAction (const QList &); + QList output; + + qCritical() << "supervoxels requires templated types!"; + + return output; +} +template QList +pcl::cloud_composer::SupervoxelsTool::performTemplatedAction( + const QList&); +// template QList +// pcl::cloud_composer::SupervoxelsTool::performTemplatedAction +// (const QList &); /////////////////// PARAMETER MODEL ///////////////////////////////// pcl::cloud_composer::PropertiesModel* -pcl::cloud_composer::SupervoxelsToolFactory::createToolParameterModel (QObject* parent) +pcl::cloud_composer::SupervoxelsToolFactory::createToolParameterModel(QObject* parent) { PropertiesModel* parameter_model = new PropertiesModel(parent); - - parameter_model->addProperty ("Resolution", 0.008, Qt::ItemIsEditable | Qt::ItemIsEnabled); - parameter_model->addProperty ("Seed Resolution", 0.08, Qt::ItemIsEditable | Qt::ItemIsEnabled); - parameter_model->addProperty ("RGB Weight", 0.2, Qt::ItemIsEditable | Qt::ItemIsEnabled); - parameter_model->addProperty ("Normals Weight", 0.8, Qt::ItemIsEditable | Qt::ItemIsEnabled); - parameter_model->addProperty ("Spatial Weight", 0.4, Qt::ItemIsEditable | Qt::ItemIsEnabled); - + + parameter_model->addProperty( + "Resolution", 0.008, Qt::ItemIsEditable | Qt::ItemIsEnabled); + parameter_model->addProperty( + "Seed Resolution", 0.08, Qt::ItemIsEditable | Qt::ItemIsEnabled); + parameter_model->addProperty( + "RGB Weight", 0.2, Qt::ItemIsEditable | Qt::ItemIsEnabled); + parameter_model->addProperty( + "Normals Weight", 0.8, Qt::ItemIsEditable | Qt::ItemIsEnabled); + parameter_model->addProperty( + "Spatial Weight", 0.4, Qt::ItemIsEditable | Qt::ItemIsEnabled); + return parameter_model; } diff --git a/apps/cloud_composer/tools/voxel_grid_downsample.cpp b/apps/cloud_composer/tools/voxel_grid_downsample.cpp index 5b15c340..3590c273 100644 --- a/apps/cloud_composer/tools/voxel_grid_downsample.cpp +++ b/apps/cloud_composer/tools/voxel_grid_downsample.cpp @@ -1,88 +1,85 @@ -#include #include - +#include #include #include - Q_PLUGIN_METADATA(IID "cloud_composer.ToolFactory/1.0") -pcl::cloud_composer::VoxelGridDownsampleTool::VoxelGridDownsampleTool (PropertiesModel* parameter_model, QObject* parent) - : ModifyItemTool (parameter_model, parent) -{ - - -} +pcl::cloud_composer::VoxelGridDownsampleTool::VoxelGridDownsampleTool( + PropertiesModel* parameter_model, QObject* parent) +: ModifyItemTool(parameter_model, parent) +{} -QList -pcl::cloud_composer::VoxelGridDownsampleTool::performAction (ConstItemList input_data, PointTypeFlags::PointType) +QList +pcl::cloud_composer::VoxelGridDownsampleTool::performAction(ConstItemList input_data, + PointTypeFlags::PointType) { - QList output; + QList output; const CloudComposerItem* input_item; // Check input data length - if ( input_data.empty ()) - { - qCritical () << "Empty input in VoxelGridDownsampleTool!"; + if (input_data.empty()) { + qCritical() << "Empty input in VoxelGridDownsampleTool!"; return output; } - if ( input_data.size () > 1) - { - qWarning () << "Input vector has more than one item in VoxelGridDownsampleTool"; + if (input_data.size() > 1) { + qWarning() << "Input vector has more than one item in VoxelGridDownsampleTool"; } - input_item = input_data.value (0); - - if (input_item->type () == CloudComposerItem::CLOUD_ITEM) - { - double leaf_x = parameter_model_->getProperty("Leaf Size x").toDouble (); - double leaf_y = parameter_model_->getProperty("Leaf Size y").toDouble (); - double leaf_z = parameter_model_->getProperty("Leaf Size z").toDouble (); - - pcl::PCLPointCloud2::ConstPtr input_cloud = input_item->data (ItemDataRole::CLOUD_BLOB).value (); - + input_item = input_data.value(0); + + if (input_item->type() == CloudComposerItem::CLOUD_ITEM) { + double leaf_x = parameter_model_->getProperty("Leaf Size x").toDouble(); + double leaf_y = parameter_model_->getProperty("Leaf Size y").toDouble(); + double leaf_z = parameter_model_->getProperty("Leaf Size z").toDouble(); + + pcl::PCLPointCloud2::ConstPtr input_cloud = + input_item->data(ItemDataRole::CLOUD_BLOB) + .value(); + //////////////// THE WORK - FILTERING OUTLIERS /////////////////// // Create the filtering object pcl::VoxelGrid vox_grid; - vox_grid.setInputCloud (input_cloud); - vox_grid.setLeafSize (float (leaf_x), float (leaf_y), float (leaf_z)); - - - //Create output cloud - pcl::PCLPointCloud2::Ptr cloud_filtered (new pcl::PCLPointCloud2); - //Filter! - vox_grid.filter (*cloud_filtered); + vox_grid.setInputCloud(input_cloud); + vox_grid.setLeafSize(float(leaf_x), float(leaf_y), float(leaf_z)); + + // Create output cloud + pcl::PCLPointCloud2::Ptr cloud_filtered(new pcl::PCLPointCloud2); + // Filter! + vox_grid.filter(*cloud_filtered); ////////////////////////////////////////////////////////////////// - //Get copies of the original origin and orientation - Eigen::Vector4f source_origin = input_item->data (ItemDataRole::ORIGIN).value (); - Eigen::Quaternionf source_orientation = input_item->data (ItemDataRole::ORIENTATION).value (); - //Put the modified cloud into an item, stick in output - CloudItem* cloud_item = new CloudItem (input_item->text () + tr (" vox ds") - , cloud_filtered - , source_origin - , source_orientation); + // Get copies of the original origin and orientation + Eigen::Vector4f source_origin = + input_item->data(ItemDataRole::ORIGIN).value(); + Eigen::Quaternionf source_orientation = + input_item->data(ItemDataRole::ORIENTATION).value(); + // Put the modified cloud into an item, stick in output + CloudItem* cloud_item = new CloudItem(input_item->text() + tr(" vox ds"), + cloud_filtered, + source_origin, + source_orientation); - - output.append (cloud_item); + output.append(cloud_item); } - else - { - qDebug () << "Input item in VoxelGridDownsampleTool is not a cloud!!!"; + else { + qDebug() << "Input item in VoxelGridDownsampleTool is not a cloud!!!"; } - - + return output; } /////////////////// PARAMETER MODEL ///////////////////////////////// pcl::cloud_composer::PropertiesModel* -pcl::cloud_composer::VoxelGridDownsampleToolFactory::createToolParameterModel (QObject* parent) +pcl::cloud_composer::VoxelGridDownsampleToolFactory::createToolParameterModel( + QObject* parent) { PropertiesModel* parameter_model = new PropertiesModel(parent); - - parameter_model->addProperty ("Leaf Size x", 0.01, Qt::ItemIsEditable | Qt::ItemIsEnabled); - parameter_model->addProperty ("Leaf Size y", 0.01, Qt::ItemIsEditable | Qt::ItemIsEnabled); - parameter_model->addProperty ("Leaf Size z", 0.01, Qt::ItemIsEditable | Qt::ItemIsEnabled); - + parameter_model->addProperty( + "Leaf Size x", 0.01, Qt::ItemIsEditable | Qt::ItemIsEnabled); + parameter_model->addProperty( + "Leaf Size y", 0.01, Qt::ItemIsEditable | Qt::ItemIsEnabled); + parameter_model->addProperty( + "Leaf Size z", 0.01, Qt::ItemIsEditable | Qt::ItemIsEnabled); + return parameter_model; } diff --git a/apps/point_cloud_editor/include/pcl/apps/point_cloud_editor/cloudEditorWidget.h b/apps/point_cloud_editor/include/pcl/apps/point_cloud_editor/cloudEditorWidget.h index 91ff49e3..9a47a025 100644 --- a/apps/point_cloud_editor/include/pcl/apps/point_cloud_editor/cloudEditorWidget.h +++ b/apps/point_cloud_editor/include/pcl/apps/point_cloud_editor/cloudEditorWidget.h @@ -51,6 +51,7 @@ #include +#include // for std::array #include class Selection; diff --git a/apps/point_cloud_editor/src/cloudEditorWidget.cpp b/apps/point_cloud_editor/src/cloudEditorWidget.cpp index f4cd6d4d..e442aada 100644 --- a/apps/point_cloud_editor/src/cloudEditorWidget.cpp +++ b/apps/point_cloud_editor/src/cloudEditorWidget.cpp @@ -495,8 +495,11 @@ CloudEditorWidget::mousePressEvent (QMouseEvent *event) auto ratio = this->devicePixelRatio(); if (!tool_ptr_) return; - tool_ptr_ -> start(event -> x()*ratio, event -> y()*ratio, - event -> modifiers(), event -> buttons()); +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) + tool_ptr_ -> start(event -> position().x()*ratio, event -> position().y()*ratio, event -> modifiers(), event -> buttons()); +#else + tool_ptr_ -> start(event -> x()*ratio, event -> y()*ratio, event -> modifiers(), event -> buttons()); +#endif update(); } @@ -506,8 +509,11 @@ CloudEditorWidget::mouseMoveEvent (QMouseEvent *event) auto ratio = this->devicePixelRatio(); if (!tool_ptr_) return; - tool_ptr_ -> update(event -> x()*ratio, event -> y()*ratio, - event -> modifiers(), event -> buttons()); +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) + tool_ptr_ -> update(event -> position().x()*ratio, event -> position().y()*ratio, event -> modifiers(), event -> buttons()); +#else + tool_ptr_ -> update(event -> x()*ratio, event -> y()*ratio, event -> modifiers(), event -> buttons()); +#endif update(); } @@ -517,8 +523,11 @@ CloudEditorWidget::mouseReleaseEvent (QMouseEvent *event) auto ratio = this->devicePixelRatio(); if (!tool_ptr_) return; - tool_ptr_ -> end(event -> x()*ratio, event -> y()*ratio, - event -> modifiers(), event -> button()); +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) + tool_ptr_ -> end(event -> position().x()*ratio, event -> position().y()*ratio, event -> modifiers(), event -> button()); +#else + tool_ptr_ -> end(event -> x()*ratio, event -> y()*ratio, event -> modifiers(), event -> button()); +#endif update(); } diff --git a/apps/src/ppf_object_recognition.cpp b/apps/src/ppf_object_recognition.cpp index b12ac2a0..9889d0c6 100644 --- a/apps/src/ppf_object_recognition.cpp +++ b/apps/src/ppf_object_recognition.cpp @@ -9,6 +9,7 @@ #include #include +#include #include using namespace pcl; diff --git a/benchmarks/CMakeLists.txt b/benchmarks/CMakeLists.txt index bf353c70..41c16091 100644 --- a/benchmarks/CMakeLists.txt +++ b/benchmarks/CMakeLists.txt @@ -29,7 +29,6 @@ PCL_ADD_BENCHMARK(filters_radius_outlier_removal FILES filters/radius_outlier_re "${PCL_SOURCE_DIR}/test/milk_cartoon_all_small_clorox.pcd") PCL_ADD_BENCHMARK(search_radius_search FILES search/radius_search.cpp - LINK_WITH pcl_io pcl_search - ARGUMENTS "${PCL_SOURCE_DIR}/test/table_scene_mug_stereo_textured.pcd" - "${PCL_SOURCE_DIR}/test/milk_cartoon_all_small_clorox.pcd") - + LINK_WITH pcl_io pcl_search pcl_filters + ARGUMENTS "${PCL_SOURCE_DIR}/test/table_scene_mug_stereo_textured.pcd") + \ No newline at end of file diff --git a/benchmarks/search/radius_search.cpp b/benchmarks/search/radius_search.cpp index 12336a8f..d6b391e1 100644 --- a/benchmarks/search/radius_search.cpp +++ b/benchmarks/search/radius_search.cpp @@ -1,4 +1,7 @@ +#include #include +#include +#include #include #include #include @@ -7,42 +10,61 @@ #include -static void -BM_OrganizedNeighborSearch(benchmark::State& state, const std::string& file) +void +print_help() { - pcl::PointCloud::Ptr cloudIn(new pcl::PointCloud); - pcl::PCDReader reader; - reader.read(file, *cloudIn); - - pcl::search::OrganizedNeighbor organizedNeighborSearch; - organizedNeighborSearch.setInputCloud(cloudIn); + std::cout << "Usage: benchmark_radius_search \n"; + std::cout << "Additional argument options:\n"; + std::cout << "Usage: benchmark_radius_search " + "\n"; +} - double radiusSearchTime = 0; - std::vector indices(cloudIn->size()); // Fixed indices from 0 to cloud size - std::iota(indices.begin(), indices.end(), 0); +static void +BM_RadiusSearch(benchmark::State& state, + const pcl::search::Search& search, + const pcl::PointCloud::Ptr cloudIn, + const double searchRadius, + const size_t neighborLimit) +{ int radiusSearchIdx = 0; + pcl::Indices k_indices; + std::vector k_sqr_distances; for (auto _ : state) { - int searchIdx = indices[radiusSearchIdx++ % indices.size()]; - double searchRadius = 0.1; // or any fixed radius like 0.05 + state.PauseTiming(); + int searchIdx = radiusSearchIdx++ % cloudIn->size(); + while (!pcl::isFinite((*cloudIn)[searchIdx])) { + searchIdx = radiusSearchIdx++ % cloudIn->size(); + } + state.ResumeTiming(); + search.radiusSearch( + (*cloudIn)[searchIdx], searchRadius, k_indices, k_sqr_distances, neighborLimit); + } +} - pcl::Indices k_indices; - std::vector k_sqr_distances; +static void +BM_KdTreeAll(benchmark::State& state, + const pcl::PointCloud::Ptr cloudIn, + const double searchRadius, + const size_t neighborLimit) +{ + pcl::search::KdTree kdtree(false); + kdtree.setInputCloud(cloudIn); + // Leaving indices empty to have it search through all points + pcl::Indices indices; + std::vector k_indices; + std::vector> k_sqr_distances; + for (auto _ : state) { auto start_time = std::chrono::high_resolution_clock::now(); - organizedNeighborSearch.radiusSearch( - (*cloudIn)[searchIdx], searchRadius, k_indices, k_sqr_distances); + kdtree.radiusSearch( + *cloudIn, indices, searchRadius, k_indices, k_sqr_distances, neighborLimit); auto end_time = std::chrono::high_resolution_clock::now(); - - radiusSearchTime += - std::chrono::duration_cast(end_time - start_time) - .count(); + std::chrono::duration elapsed = end_time - start_time; + state.SetIterationTime(elapsed.count() / cloudIn->size()); } - state.SetItemsProcessed(state.iterations()); - state.SetIterationTime( - radiusSearchTime / - (state.iterations() * indices.size())); // Normalize by total points processed + state.SetItemsProcessed(cloudIn->size()); } int @@ -51,12 +73,73 @@ main(int argc, char** argv) if (argc < 2) { std::cerr << "No test file given. Please provide a PCD file for the benchmark." << std::endl; + print_help(); return -1; } + pcl::PointCloud::Ptr cloudIn(new pcl::PointCloud); + pcl::PCDReader reader; + reader.read(argv[1], *cloudIn); + + // Filter out nans + pcl::PointCloud::Ptr cloudFiltered(new pcl::PointCloud); + pcl::Indices indices; + pcl::removeNaNFromPointCloud(*cloudIn, *cloudFiltered, indices); + + double searchRadius = 0.1; + if (argc > 2) { + try { + searchRadius = std::abs(std::stod(argv[2])); + } catch (const std::invalid_argument&) { + std::cerr << "Error: Invalid search radius. Setting it to a default of 0.1." + << std::endl; + } + } + + size_t neighborLimit = 0u; + if (argc > 3) { + try { + neighborLimit = std::stoul(argv[3]); + } catch (const std::invalid_argument&) { + std::cerr << "Error: Invalid neighbor limit. Setting it to a default of int max." + << std::endl; + } + } + + pcl::search::OrganizedNeighbor organized_neighbor; + organized_neighbor.setInputCloud(cloudIn); + benchmark::RegisterBenchmark("OrganizedNeighborSearch", + &BM_RadiusSearch, + organized_neighbor, + cloudIn, + searchRadius, + neighborLimit) + ->Unit(benchmark::kMicrosecond); + + pcl::search::KdTree kdtree(false); + kdtree.setInputCloud(cloudIn); + benchmark::RegisterBenchmark( + "KdTree", &BM_RadiusSearch, kdtree, cloudIn, searchRadius, neighborLimit) + ->Unit(benchmark::kMicrosecond); + benchmark::RegisterBenchmark( - "BM_OrganizedNeighborSearch", &BM_OrganizedNeighborSearch, argv[1]) - ->Unit(benchmark::kMillisecond); + "KdTreeAll", &BM_KdTreeAll, cloudFiltered, searchRadius, neighborLimit) + ->Unit(benchmark::kMicrosecond) + ->UseManualTime() + ->Iterations(1); + +#if PCL_HAS_NANOFLANN + pcl::search::KdTreeNanoflann kdtreeNanoflann; + kdtreeNanoflann.setInputCloud(cloudIn); + benchmark::RegisterBenchmark("KdTreeNanoflann", + &BM_RadiusSearch, + kdtreeNanoflann, + cloudIn, + searchRadius, + neighborLimit) + ->Unit(benchmark::kMicrosecond); +#endif + benchmark::Initialize(&argc, argv); benchmark::RunSpecifiedBenchmarks(); } diff --git a/cmake/pcl_alignment.cmake b/cmake/pcl_alignment.cmake new file mode 100644 index 00000000..55ff9875 --- /dev/null +++ b/cmake/pcl_alignment.cmake @@ -0,0 +1,31 @@ +############################################################################### +# Check for the presence of _mm_malloc() and posix_memalign() +function(PCL_CHECK_FOR_ALIGNMENT) + include(CheckCXXSourceCompiles) + if(NOT DEFINED HAVE_MM_MALLOC) + check_cxx_source_compiles(" + // Intel compiler defines an incompatible _mm_malloc signature + #if defined(__INTEL_COMPILER) + #include + #else + #include + #endif + int main() + { + void* mem = _mm_malloc (100, 16); + return 0; + }" + HAVE_MM_MALLOC) + endif() + + if(NOT DEFINED HAVE_POSIX_MEMALIGN) + check_cxx_source_compiles(" + #include + int main() + { + void* mem; + return posix_memalign (&mem, 16, 100); + }" + HAVE_POSIX_MEMALIGN) + endif() +endfunction() diff --git a/cmake/pcl_all_in_one_installer.cmake b/cmake/pcl_all_in_one_installer.cmake index 22cf0948..8b993d4b 100644 --- a/cmake/pcl_all_in_one_installer.cmake +++ b/cmake/pcl_all_in_one_installer.cmake @@ -8,14 +8,15 @@ if(NOT BUILD_all_in_one_installer) endif() # get root directory of each dependency libraries to be copied to PCL/3rdParty -get_filename_component(BOOST_ROOT "${Boost_INCLUDE_DIR}" PATH) # ../Boost/include/boost-x_x/ -> ../Boost/include/ -get_filename_component(BOOST_ROOT "${BOOST_ROOT}" PATH) # ../Boost/include/ -> ../Boost/ -get_filename_component(QHULL_ROOT "${Qhull_DIR}" PATH) # ../qhull/lib/cmake/Qhull/ -> ../qhull/lib/cmake -get_filename_component(QHULL_ROOT "${QHULL_ROOT}" PATH) # ../qhull/lib/cmake/ -> ../qhull/lib/ -get_filename_component(QHULL_ROOT "${QHULL_ROOT}" PATH) # ../qhull/lib/ -> ../qhull/ -get_filename_component(VTK_ROOT "${VTK_DIR}" PATH) # ../VTK/lib/cmake/vtk-x.x/ -> ../VTK/lib/cmake/ -get_filename_component(VTK_ROOT "${VTK_ROOT}" PATH) # ../VTK/lib/cmake/ -> ../VTK/lib/ -get_filename_component(VTK_ROOT "${VTK_ROOT}" PATH) # ../VTK/lib/ -> ../VTK/ +get_filename_component(BOOST_ROOT "${Boost_DIR}" PATH) # ../Boost/lib/cmake/Boost-X.XX.X/ -> ../Boost/lib/cmake/ +get_filename_component(BOOST_ROOT "${BOOST_ROOT}" PATH) # ../Boost/lib/cmake/ -> ../Boost/lib/ +get_filename_component(BOOST_ROOT "${BOOST_ROOT}" PATH) # ../Boost/lib/ -> ../Boost/ +get_filename_component(QHULL_ROOT "${Qhull_DIR}" PATH) # ../qhull/lib/cmake/Qhull/ -> ../qhull/lib/cmake +get_filename_component(QHULL_ROOT "${QHULL_ROOT}" PATH) # ../qhull/lib/cmake/ -> ../qhull/lib/ +get_filename_component(QHULL_ROOT "${QHULL_ROOT}" PATH) # ../qhull/lib/ -> ../qhull/ +get_filename_component(VTK_ROOT "${VTK_DIR}" PATH) # ../VTK/lib/cmake/vtk-x.x/ -> ../VTK/lib/cmake/ +get_filename_component(VTK_ROOT "${VTK_ROOT}" PATH) # ../VTK/lib/cmake/ -> ../VTK/lib/ +get_filename_component(VTK_ROOT "${VTK_ROOT}" PATH) # ../VTK/lib/ -> ../VTK/ set(PCL_3RDPARTY_COMPONENTS) foreach(dep Boost Qhull FLANN VTK) diff --git a/cmake/pcl_find_avx.cmake b/cmake/pcl_find_avx.cmake index f760a163..216e4670 100644 --- a/cmake/pcl_find_avx.cmake +++ b/cmake/pcl_find_avx.cmake @@ -3,15 +3,15 @@ function(PCL_CHECK_FOR_AVX) set(AVX_FLAGS) - include(CheckCXXSourceRuns) + include(CheckCXXSourceCompiles) if(CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_GNUCXX OR CMAKE_COMPILER_IS_CLANG) - # Setting -march & -mtune just as required flags for check_cxx_source_runs, - # and CMAKE_REQUIRED_FLAGS will be restored after test runs. + # Setting -march & -mtune just as required flags for check_cxx_source_compiles, + # and CMAKE_REQUIRED_FLAGS will be restored after test compiles. set(CMAKE_REQUIRED_FLAGS "-march=native -mtune=native") endif() - check_cxx_source_runs(" + check_cxx_source_compiles(" #include int main() { @@ -22,7 +22,7 @@ function(PCL_CHECK_FOR_AVX) HAVE_AVX2) if(NOT HAVE_AVX2) - check_cxx_source_runs(" + check_cxx_source_compiles(" #include int main() { diff --git a/cmake/pcl_find_boost.cmake b/cmake/pcl_find_boost.cmake index 5d5c7859..381024ea 100644 --- a/cmake/pcl_find_boost.cmake +++ b/cmake/pcl_find_boost.cmake @@ -15,14 +15,14 @@ endif() if(CMAKE_CXX_STANDARD MATCHES "14") # Optional boost modules - set(BOOST_OPTIONAL_MODULES serialization mpi) + set(BOOST_OPTIONAL_MODULES serialization mpi system) # Required boost modules - set(BOOST_REQUIRED_MODULES filesystem iostreams system) + set(BOOST_REQUIRED_MODULES filesystem iostreams) else() # Optional boost modules - set(BOOST_OPTIONAL_MODULES filesystem serialization mpi) + set(BOOST_OPTIONAL_MODULES filesystem serialization mpi system) # Required boost modules - set(BOOST_REQUIRED_MODULES iostreams system) + set(BOOST_REQUIRED_MODULES iostreams) endif() find_package(Boost 1.71.0 QUIET COMPONENTS ${BOOST_OPTIONAL_MODULES} CONFIG) diff --git a/cmake/pcl_find_sse.cmake b/cmake/pcl_find_sse.cmake index 25d1522b..4661abf1 100644 --- a/cmake/pcl_find_sse.cmake +++ b/cmake/pcl_find_sse.cmake @@ -19,38 +19,15 @@ function(PCL_CHECK_FOR_SSE) # precision). One solution would be to use "-ffloat-store" on 32bit (see # http://gcc.gnu.org/onlinedocs/gcc/Optimize-Options.html), but that slows code down, # so the preferred solution is to try "-mpfmath=sse" first. - include(CheckCXXSourceRuns) + include(CheckCXXSourceCompiles) set(CMAKE_REQUIRED_FLAGS) set(SSE_LEVEL 0) - check_cxx_source_runs(" - // Intel compiler defines an incompatible _mm_malloc signature - #if defined(__INTEL_COMPILER) - #include - #else - #include - #endif - int main() - { - void* mem = _mm_malloc (100, 16); - return 0; - }" - HAVE_MM_MALLOC) - - check_cxx_source_runs(" - #include - int main() - { - void* mem; - return posix_memalign (&mem, 16, 100); - }" - HAVE_POSIX_MEMALIGN) - if(CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_GNUCXX OR CMAKE_COMPILER_IS_CLANG) set(CMAKE_REQUIRED_FLAGS "-msse4.2") endif() - check_cxx_source_runs(" + check_cxx_source_compiles(" #include #include int main () @@ -79,7 +56,7 @@ function(PCL_CHECK_FOR_SSE) set(CMAKE_REQUIRED_FLAGS "-msse4.1") endif() - check_cxx_source_runs(" + check_cxx_source_compiles(" #include int main () { @@ -104,7 +81,7 @@ function(PCL_CHECK_FOR_SSE) set(CMAKE_REQUIRED_FLAGS "-mssse3") endif() - check_cxx_source_runs(" + check_cxx_source_compiles(" #include int main () { @@ -127,7 +104,7 @@ function(PCL_CHECK_FOR_SSE) set(CMAKE_REQUIRED_FLAGS "-msse3") endif() - check_cxx_source_runs(" + check_cxx_source_compiles(" #include int main () { @@ -152,7 +129,7 @@ function(PCL_CHECK_FOR_SSE) set(CMAKE_REQUIRED_FLAGS "/arch:SSE2") endif() - check_cxx_source_runs(" + check_cxx_source_compiles(" #include int main () { @@ -177,7 +154,7 @@ function(PCL_CHECK_FOR_SSE) set(CMAKE_REQUIRED_FLAGS "/arch:SSE") endif() - check_cxx_source_runs(" + check_cxx_source_compiles(" #include int main () { diff --git a/cmake/pcl_options.cmake b/cmake/pcl_options.cmake index 1c9781e0..4ecccfe3 100644 --- a/cmake/pcl_options.cmake +++ b/cmake/pcl_options.cmake @@ -66,12 +66,15 @@ mark_as_advanced(PCL_ONLY_CORE_POINT_TYPES) option(PCL_NO_PRECOMPILE "Do not precompile PCL code for any point types at all." OFF) mark_as_advanced(PCL_NO_PRECOMPILE) -# Enable or Disable the check for SSE optimizations +# Enable or Disable the check for SSE and AVX optimizations +if(CMAKE_SYSTEM_PROCESSOR MATCHES "arm") +option(PCL_ENABLE_SSE "Enable or Disable SSE optimizations." OFF) +option(PCL_ENABLE_AVX "Enable or Disable AVX optimizations." OFF) +else() option(PCL_ENABLE_SSE "Enable or Disable SSE optimizations." ON) -mark_as_advanced(PCL_ENABLE_SSE) - -# Enable or Disable the check for AVX optimizations option(PCL_ENABLE_AVX "Enable or Disable AVX optimizations." ON) +endif() +mark_as_advanced(PCL_ENABLE_SSE) mark_as_advanced(PCL_ENABLE_AVX) if(UNIX) diff --git a/common/include/pcl/common/concatenate.h b/common/include/pcl/common/concatenate.h index f7510812..18f79266 100644 --- a/common/include/pcl/common/concatenate.h +++ b/common/include/pcl/common/concatenate.h @@ -62,13 +62,8 @@ namespace pcl //boost::fusion::at_key (p2_) = boost::fusion::at_key (p1_); using InT = typename pcl::traits::datatype::type; using OutT = typename pcl::traits::datatype::type; - // Note: don't currently support different types for the same field (e.g. converting double to float) - BOOST_MPL_ASSERT_MSG ((std::is_same::value), - POINT_IN_AND_POINT_OUT_HAVE_DIFFERENT_TYPES_FOR_FIELD, - (Key, PointInT&, InT, PointOutT&, OutT)); - memcpy (reinterpret_cast(&p2_) + pcl::traits::offset::value, - reinterpret_cast(&p1_) + pcl::traits::offset::value, - sizeof (InT)); + *reinterpret_cast(reinterpret_cast(&p2_) + pcl::traits::offset::value) = + *reinterpret_cast(reinterpret_cast(&p1_) + pcl::traits::offset::value); } private: diff --git a/common/include/pcl/common/impl/centroid.hpp b/common/include/pcl/common/impl/centroid.hpp index bc0885be..ece0d11d 100644 --- a/common/include/pcl/common/impl/centroid.hpp +++ b/common/include/pcl/common/impl/centroid.hpp @@ -696,7 +696,7 @@ computeCentroidAndOBB (const pcl::PointCloud &cloud, //[0 , 1 ] Eigen::Matrix transform = Eigen::Matrix::Identity(); transform.template topLeftCorner<3, 3>() = obb_rotational_matrix.transpose(); - transform.template topRightCorner<3, 1>() =-transform.template topLeftCorner<3, 3>()*centroid; + transform.template topRightCorner<3, 1>().noalias() =-transform.template topLeftCorner<3, 3>()*centroid; //when Scalar==double on a Windows 10 machine and MSVS: //if you substitute the following Scalars with floats you get a 20% worse processing time, if with 2 PointT 55% worse @@ -786,7 +786,7 @@ computeCentroidAndOBB (const pcl::PointCloud &cloud, obb_dimensions(1) = obb_max_pointy - obb_min_pointy; obb_dimensions(2) = obb_max_pointz - obb_min_pointz; - obb_center = centroid + obb_rotational_matrix * shift;//position of the OBB center in the same reference Oxyz of the point cloud + obb_center.noalias() = centroid + obb_rotational_matrix * shift;//position of the OBB center in the same reference Oxyz of the point cloud return (point_count); } @@ -830,7 +830,7 @@ computeCentroidAndOBB (const pcl::PointCloud &cloud, //[0 , 1 ] Eigen::Matrix transform = Eigen::Matrix::Identity(); transform.template topLeftCorner<3, 3>() = obb_rotational_matrix.transpose(); - transform.template topRightCorner<3, 1>() =-transform.template topLeftCorner<3, 3>()*centroid; + transform.template topRightCorner<3, 1>().noalias() =-transform.template topLeftCorner<3, 3>()*centroid; //when Scalar==double on a Windows 10 machine and MSVS: //if you substitute the following Scalars with floats you get a 20% worse processing time, if with 2 PointT 55% worse @@ -922,7 +922,7 @@ computeCentroidAndOBB (const pcl::PointCloud &cloud, obb_dimensions(1) = obb_max_pointy - obb_min_pointy; obb_dimensions(2) = obb_max_pointz - obb_min_pointz; - obb_center = centroid + obb_rotational_matrix * shift;//position of the OBB center in the same reference Oxyz of the point cloud + obb_center.noalias() = centroid + obb_rotational_matrix * shift;//position of the OBB center in the same reference Oxyz of the point cloud return (point_count); } diff --git a/common/include/pcl/common/impl/eigen.hpp b/common/include/pcl/common/impl/eigen.hpp index 8f628f1d..e9b9f86b 100644 --- a/common/include/pcl/common/impl/eigen.hpp +++ b/common/include/pcl/common/impl/eigen.hpp @@ -912,8 +912,8 @@ transformBetween2CoordinateSystems (const Eigen::Matrix transformation = T3 transformation = Eigen::Transform::Identity (); - transformation.linear () = T3.linear () * T2.linear ().inverse (); - transformation.translation () = to0 - (transformation.linear () * fr0); + transformation.linear ().noalias () = T3.linear () * T2.linear ().inverse (); + transformation.translation ().noalias () = to0 - (transformation.linear () * fr0); return (true); } diff --git a/common/include/pcl/common/impl/pca.hpp b/common/include/pcl/common/impl/pca.hpp index 3bebb2be..2d0f4187 100644 --- a/common/include/pcl/common/impl/pca.hpp +++ b/common/include/pcl/common/impl/pca.hpp @@ -86,7 +86,7 @@ PCA::initCompute () eigenvectors_.col(2) = eigenvectors_.col(0).cross(eigenvectors_.col(1)); // If not basis only then compute the coefficients if (!basis_only_) - coefficients_ = eigenvectors_.transpose() * cloud_demean.topRows<3> (); + coefficients_.noalias() = eigenvectors_.transpose() * cloud_demean.topRows<3> (); compute_done_ = true; return (true); } @@ -171,7 +171,7 @@ PCA::project (const PointT& input, PointT& projection) PCL_THROW_EXCEPTION (InitFailedException, "[pcl::PCA::project] PCA initCompute failed"); Eigen::Vector3f demean_input = input.getVector3fMap () - mean_.head<3> (); - projection.getVector3fMap () = eigenvectors_.transpose() * demean_input; + projection.getVector3fMap ().noalias () = eigenvectors_.transpose() * demean_input; } diff --git a/common/include/pcl/common/impl/polynomial_calculations.hpp b/common/include/pcl/common/impl/polynomial_calculations.hpp index 6b2f2888..78cb72ea 100644 --- a/common/include/pcl/common/impl/polynomial_calculations.hpp +++ b/common/include/pcl/common/impl/polynomial_calculations.hpp @@ -482,7 +482,7 @@ PolynomialCalculationsT::bivariatePolynomialApproximation ( //std::cout << "Cholesky took "<< (choleskyStartTime+get_time ())*1000<<"ms.\n"; //double invStartTime=-get_time (); - parameters = A.inverse () * b; + parameters.noalias() = A.inverse () * b; //std::cout << "Inverse took "<< (invStartTime+get_time ())*1000<<"ms.\n"; //std::cout << PVARC (A)<1e-5 && std::abs(eigen_vectors.coeff (132))<1e-7) + projection_matrix /= projection_matrix.coeffRef (10); + return (residual); } diff --git a/common/include/pcl/impl/pcl_base.hpp b/common/include/pcl/impl/pcl_base.hpp index 6e548958..93d6c384 100644 --- a/common/include/pcl/impl/pcl_base.hpp +++ b/common/include/pcl/impl/pcl_base.hpp @@ -164,7 +164,7 @@ pcl::PCLBase::initCompute () PCL_ERROR ("[initCompute] Failed to allocate %lu indices.\n", input_->size ()); return (false); } - for (auto i = indices_size; i < indices_->size (); ++i) { (*indices_)[i] = static_cast(i); } + for (auto i = indices_size; i < indices_->size (); ++i) { (*indices_)[i] = i; } } return (true); diff --git a/common/include/pcl/point_cloud.h b/common/include/pcl/point_cloud.h index f7b63ba7..56063536 100644 --- a/common/include/pcl/point_cloud.h +++ b/common/include/pcl/point_cloud.h @@ -52,6 +52,7 @@ #include #include // for PCL_WARN +#include // for assert #include #include diff --git a/cuda/sample_consensus/src/sac_model_1point_plane.cu b/cuda/sample_consensus/src/sac_model_1point_plane.cu index c68e260f..033de426 100644 --- a/cuda/sample_consensus/src/sac_model_1point_plane.cu +++ b/cuda/sample_consensus/src/sac_model_1point_plane.cu @@ -326,7 +326,7 @@ namespace pcl //thrust::counting_iterator first (0); // Input: Point Cloud, Indices // Output: Hypotheses - transform (//first, first + max_iterations, + thrust::transform (//first, first + max_iterations, //index_sequence_begin, //index_sequence_begin + max_iterations, randoms.begin (), randoms.begin () + max_iterations, @@ -360,7 +360,7 @@ namespace pcl //thrust::counting_iterator first (0); // Input: Point Cloud, Indices // Output: Hypotheses - transform (//first, first + max_iterations, + thrust::transform (//first, first + max_iterations, //index_sequence_begin, //index_sequence_begin + max_iterations, randoms.begin (), randoms.begin () + max_iterations, @@ -555,7 +555,7 @@ namespace pcl coefficients.z = model_coefficients[2]; coefficients.w = model_coefficients[3]; - return (int) count_if ( + return (int) thrust::count_if ( make_zip_iterator (make_tuple (input_->points.begin (), indices_->begin ())), make_zip_iterator (make_tuple (input_->points.begin (), indices_->begin ())) + indices_->size (), @@ -608,7 +608,7 @@ namespace pcl { // pcl::ScopeTime t ("transform"); // Send the data to the device - transform ( + thrust::transform ( make_zip_iterator (make_tuple (input_->points.begin (), indices_->begin ())), make_zip_iterator (make_tuple (input_->points.begin (), indices_->begin ())) + nr_points, @@ -667,7 +667,7 @@ namespace pcl { // pcl::ScopeTime t ("transform"); // Send the data to the device - transform ( + thrust::transform ( make_zip_iterator (make_tuple (input_->points.begin (), indices_->begin ())), make_zip_iterator (make_tuple (input_->points.begin (), indices_->begin ())) + nr_points, diff --git a/cuda/sample_consensus/src/sac_model_plane.cu b/cuda/sample_consensus/src/sac_model_plane.cu index cf8a6a22..7eb91e1f 100644 --- a/cuda/sample_consensus/src/sac_model_plane.cu +++ b/cuda/sample_consensus/src/sac_model_plane.cu @@ -238,7 +238,7 @@ namespace pcl coefficients.z = model_coefficients[2]; coefficients.w = model_coefficients[3]; - return (int) count_if ( + return (int) thrust::count_if ( make_zip_iterator (make_tuple (input_->points.begin (), indices_->begin ())), make_zip_iterator (make_tuple (input_->points.begin (), indices_->begin ())) + indices_->size (), @@ -286,7 +286,7 @@ namespace pcl coefficients.w = model_coefficients[3]; // Send the data to the device - transform ( + thrust::transform ( make_zip_iterator (make_tuple (input_->points.begin (), indices_->begin ())), make_zip_iterator (make_tuple (input_->points.begin (), indices_->begin ())) + nr_points, @@ -331,7 +331,7 @@ namespace pcl coefficients.w = ((float4)h[idx]).w; // Send the data to the device - transform ( + thrust::transform ( make_zip_iterator (make_tuple (input_->points.begin (), indices_->begin ())), make_zip_iterator (make_tuple (input_->points.begin (), indices_->begin ())) + nr_points, @@ -372,7 +372,7 @@ namespace pcl coefficients.z = ((float4)h[idx]).z; coefficients.w = ((float4)h[idx]).w; - transform ( + thrust::transform ( make_zip_iterator (make_tuple (input_->points.begin (), indices_->begin ())), make_zip_iterator (make_tuple (input_->points.begin (), indices_->begin ())) + nr_points, diff --git a/doc/tutorials/content/dinast_grabber.rst b/doc/tutorials/content/dinast_grabber.rst index d83c1e47..50b89a0f 100644 --- a/doc/tutorials/content/dinast_grabber.rst +++ b/doc/tutorials/content/dinast_grabber.rst @@ -161,10 +161,6 @@ We will test the grabber with the previous example. Write down the whole code to find_package(PCL 1.7 REQUIRED) - include_directories(${PCL_INCLUDE_DIRS}) - link_directories(${PCL_LIBRARY_DIRS}) - add_definitions(${PCL_DEFINITIONS}) - add_executable (dinast_grabber dinast_grabber.cpp) target_link_libraries (dinast_grabber ${PCL_LIBRARIES}) diff --git a/doc/tutorials/content/hdl_grabber.rst b/doc/tutorials/content/hdl_grabber.rst index ba1b9f50..e4c8c64f 100644 --- a/doc/tutorials/content/hdl_grabber.rst +++ b/doc/tutorials/content/hdl_grabber.rst @@ -213,10 +213,6 @@ Add the following lines to your CMakeLists.txt file: find_package(PCL 1.2 REQUIRED) - include_directories(${PCL_INCLUDE_DIRS}) - link_directories(${PCL_LIBRARY_DIRS}) - add_definitions(${PCL_DEFINITIONS}) - add_executable(pcl_hdl_viewer_simple hdl_viewer_simple.cpp) target_link_libraries(pcl_hdl_viewer_simple ${PCL_LIBRARIES}) diff --git a/doc/tutorials/content/sources/alignment_prerejective/CMakeLists.txt b/doc/tutorials/content/sources/alignment_prerejective/CMakeLists.txt index 64dbfd37..8d1a2161 100644 --- a/doc/tutorials/content/sources/alignment_prerejective/CMakeLists.txt +++ b/doc/tutorials/content/sources/alignment_prerejective/CMakeLists.txt @@ -4,9 +4,5 @@ project(alignment_prerejective) find_package(PCL 1.7 REQUIRED COMPONENTS io registration segmentation visualization) -include_directories(${PCL_INCLUDE_DIRS}) -link_directories(${PCL_LIBRARY_DIRS}) -add_definitions(${PCL_DEFINITIONS}) - add_executable (alignment_prerejective alignment_prerejective.cpp) target_link_libraries (alignment_prerejective ${PCL_LIBRARIES}) diff --git a/doc/tutorials/content/sources/bare_earth/CMakeLists.txt b/doc/tutorials/content/sources/bare_earth/CMakeLists.txt index 4cf8a63c..8d63d908 100644 --- a/doc/tutorials/content/sources/bare_earth/CMakeLists.txt +++ b/doc/tutorials/content/sources/bare_earth/CMakeLists.txt @@ -4,9 +4,5 @@ project(bare_earth) find_package(PCL 1.7.2 REQUIRED) -include_directories(${PCL_INCLUDE_DIRS}) -link_directories(${PCL_LIBRARY_DIRS}) -add_definitions(${PCL_DEFINITIONS}) - add_executable (bare_earth bare_earth.cpp) target_link_libraries (bare_earth ${PCL_LIBRARIES}) diff --git a/doc/tutorials/content/sources/bspline_fitting/CMakeLists.txt b/doc/tutorials/content/sources/bspline_fitting/CMakeLists.txt index 7742fc76..2b85dd2d 100644 --- a/doc/tutorials/content/sources/bspline_fitting/CMakeLists.txt +++ b/doc/tutorials/content/sources/bspline_fitting/CMakeLists.txt @@ -4,9 +4,5 @@ project(bspline_fitting) find_package(PCL 1.7 REQUIRED) -include_directories(${PCL_INCLUDE_DIRS}) -link_directories(${PCL_LIBRARY_DIRS}) -add_definitions(${PCL_DEFINITIONS}) - add_executable (bspline_fitting bspline_fitting.cpp) target_link_libraries (bspline_fitting ${PCL_LIBRARIES}) diff --git a/doc/tutorials/content/sources/cloud_viewer/CMakeLists.txt b/doc/tutorials/content/sources/cloud_viewer/CMakeLists.txt index 43bff93b..d2014c91 100644 --- a/doc/tutorials/content/sources/cloud_viewer/CMakeLists.txt +++ b/doc/tutorials/content/sources/cloud_viewer/CMakeLists.txt @@ -4,9 +4,5 @@ project(cloud_viewer) find_package(PCL 1.2 REQUIRED) -include_directories(${PCL_INCLUDE_DIRS}) -link_directories(${PCL_LIBRARY_DIRS}) -add_definitions(${PCL_DEFINITIONS}) - add_executable (cloud_viewer cloud_viewer.cpp) target_link_libraries (cloud_viewer ${PCL_LIBRARIES}) diff --git a/doc/tutorials/content/sources/cluster_extraction/CMakeLists.txt b/doc/tutorials/content/sources/cluster_extraction/CMakeLists.txt index 5a186fb9..00dbf55b 100644 --- a/doc/tutorials/content/sources/cluster_extraction/CMakeLists.txt +++ b/doc/tutorials/content/sources/cluster_extraction/CMakeLists.txt @@ -4,9 +4,5 @@ project(cluster_extraction) find_package(PCL 1.2 REQUIRED) -include_directories(${PCL_INCLUDE_DIRS}) -link_directories(${PCL_LIBRARY_DIRS}) -add_definitions(${PCL_DEFINITIONS}) - add_executable (cluster_extraction cluster_extraction.cpp) target_link_libraries (cluster_extraction ${PCL_LIBRARIES}) diff --git a/doc/tutorials/content/sources/concatenate_clouds/CMakeLists.txt b/doc/tutorials/content/sources/concatenate_clouds/CMakeLists.txt index 01d85087..b70e097f 100644 --- a/doc/tutorials/content/sources/concatenate_clouds/CMakeLists.txt +++ b/doc/tutorials/content/sources/concatenate_clouds/CMakeLists.txt @@ -4,9 +4,5 @@ project(concatenate_clouds) find_package(PCL 1.2 REQUIRED) -include_directories(${PCL_INCLUDE_DIRS}) -link_directories(${PCL_LIBRARY_DIRS}) -add_definitions(${PCL_DEFINITIONS}) - add_executable (concatenate_clouds concatenate_clouds.cpp) target_link_libraries (concatenate_clouds ${PCL_LIBRARIES}) diff --git a/doc/tutorials/content/sources/concatenate_fields/CMakeLists.txt b/doc/tutorials/content/sources/concatenate_fields/CMakeLists.txt index adb6cff6..7fcc10bc 100644 --- a/doc/tutorials/content/sources/concatenate_fields/CMakeLists.txt +++ b/doc/tutorials/content/sources/concatenate_fields/CMakeLists.txt @@ -4,9 +4,5 @@ project(concatenate_fields) find_package(PCL 1.2 REQUIRED) -include_directories(${PCL_INCLUDE_DIRS}) -link_directories(${PCL_LIBRARY_DIRS}) -add_definitions(${PCL_DEFINITIONS}) - add_executable (concatenate_fields concatenate_fields.cpp) target_link_libraries (concatenate_fields ${PCL_LIBRARIES}) diff --git a/doc/tutorials/content/sources/concatenate_points/CMakeLists.txt b/doc/tutorials/content/sources/concatenate_points/CMakeLists.txt index 80368b57..600b7487 100644 --- a/doc/tutorials/content/sources/concatenate_points/CMakeLists.txt +++ b/doc/tutorials/content/sources/concatenate_points/CMakeLists.txt @@ -4,9 +4,5 @@ project(concatenate_points) find_package(PCL 1.2 REQUIRED) -include_directories(${PCL_INCLUDE_DIRS}) -link_directories(${PCL_LIBRARY_DIRS}) -add_definitions(${PCL_DEFINITIONS}) - add_executable (concatenate_points concatenate_points.cpp) target_link_libraries (concatenate_points ${PCL_LIBRARIES}) diff --git a/doc/tutorials/content/sources/concave_hull_2d/CMakeLists.txt b/doc/tutorials/content/sources/concave_hull_2d/CMakeLists.txt index eff91289..7ad4c9ee 100644 --- a/doc/tutorials/content/sources/concave_hull_2d/CMakeLists.txt +++ b/doc/tutorials/content/sources/concave_hull_2d/CMakeLists.txt @@ -4,9 +4,5 @@ project(concave_hull_2d) find_package(PCL 1.2 REQUIRED) -include_directories(${PCL_INCLUDE_DIRS}) -link_directories(${PCL_LIBRARY_DIRS}) -add_definitions(${PCL_DEFINITIONS}) - add_executable (concave_hull_2d concave_hull_2d.cpp) target_link_libraries (concave_hull_2d ${PCL_LIBRARIES}) diff --git a/doc/tutorials/content/sources/conditional_euclidean_clustering/CMakeLists.txt b/doc/tutorials/content/sources/conditional_euclidean_clustering/CMakeLists.txt index 630217c8..ee910a2d 100644 --- a/doc/tutorials/content/sources/conditional_euclidean_clustering/CMakeLists.txt +++ b/doc/tutorials/content/sources/conditional_euclidean_clustering/CMakeLists.txt @@ -4,9 +4,5 @@ project(conditional_euclidean_clustering) find_package(PCL 1.7 REQUIRED) -include_directories(${PCL_INCLUDE_DIRS}) -link_directories(${PCL_LIBRARY_DIRS}) -add_definitions(${PCL_DEFINITIONS}) - add_executable (conditional_euclidean_clustering conditional_euclidean_clustering.cpp) target_link_libraries (conditional_euclidean_clustering ${PCL_LIBRARIES}) diff --git a/doc/tutorials/content/sources/conditional_removal/CMakeLists.txt b/doc/tutorials/content/sources/conditional_removal/CMakeLists.txt index a861eb3b..0ff26f24 100644 --- a/doc/tutorials/content/sources/conditional_removal/CMakeLists.txt +++ b/doc/tutorials/content/sources/conditional_removal/CMakeLists.txt @@ -4,9 +4,5 @@ project(conditional_removal) find_package(PCL 1.2 REQUIRED) -include_directories(${PCL_INCLUDE_DIRS}) -link_directories(${PCL_LIBRARY_DIRS}) -add_definitions(${PCL_DEFINITIONS}) - add_executable (conditional_removal conditional_removal.cpp) target_link_libraries (conditional_removal ${PCL_LIBRARIES}) diff --git a/doc/tutorials/content/sources/convex_hull_2d/CMakeLists.txt b/doc/tutorials/content/sources/convex_hull_2d/CMakeLists.txt index df4059b3..68d4e59d 100644 --- a/doc/tutorials/content/sources/convex_hull_2d/CMakeLists.txt +++ b/doc/tutorials/content/sources/convex_hull_2d/CMakeLists.txt @@ -4,9 +4,5 @@ project(convex_hull_2d) find_package(PCL 1.2 REQUIRED) -include_directories(${PCL_INCLUDE_DIRS}) -link_directories(${PCL_LIBRARY_DIRS}) -add_definitions(${PCL_DEFINITIONS}) - add_executable (convex_hull_2d convex_hull_2d.cpp) target_link_libraries (convex_hull_2d ${PCL_LIBRARIES}) diff --git a/doc/tutorials/content/sources/correspondence_grouping/CMakeLists.txt b/doc/tutorials/content/sources/correspondence_grouping/CMakeLists.txt index 8e9ecf32..fb1c2473 100644 --- a/doc/tutorials/content/sources/correspondence_grouping/CMakeLists.txt +++ b/doc/tutorials/content/sources/correspondence_grouping/CMakeLists.txt @@ -4,9 +4,5 @@ project(correspondence_grouping) find_package(PCL 1.5 REQUIRED) -include_directories(${PCL_INCLUDE_DIRS}) -link_directories(${PCL_LIBRARY_DIRS}) -add_definitions(${PCL_DEFINITIONS}) - add_executable (correspondence_grouping correspondence_grouping.cpp) target_link_libraries (correspondence_grouping ${PCL_LIBRARIES}) diff --git a/doc/tutorials/content/sources/cylinder_segmentation/CMakeLists.txt b/doc/tutorials/content/sources/cylinder_segmentation/CMakeLists.txt index 4c3bf827..1bae3a12 100644 --- a/doc/tutorials/content/sources/cylinder_segmentation/CMakeLists.txt +++ b/doc/tutorials/content/sources/cylinder_segmentation/CMakeLists.txt @@ -4,9 +4,5 @@ project(cylinder_segmentation) find_package(PCL 1.2 REQUIRED) -include_directories(${PCL_INCLUDE_DIRS}) -link_directories(${PCL_LIBRARY_DIRS}) -add_definitions(${PCL_DEFINITIONS}) - add_executable (cylinder_segmentation cylinder_segmentation.cpp) target_link_libraries (cylinder_segmentation ${PCL_LIBRARIES}) diff --git a/doc/tutorials/content/sources/davidsdk/CMakeLists.txt b/doc/tutorials/content/sources/davidsdk/CMakeLists.txt index 247cec65..8045172b 100644 --- a/doc/tutorials/content/sources/davidsdk/CMakeLists.txt +++ b/doc/tutorials/content/sources/davidsdk/CMakeLists.txt @@ -5,9 +5,6 @@ project(pcl-davidSDK_images_viewer) find_package(PCL 1.8.0 REQUIRED) find_package(OpenCV REQUIRED) -include_directories(${PCL_INCLUDE_DIRS}) -link_directories(${PCL_LIBRARY_DIRS}) -add_definitions(${PCL_DEFINITIONS}) add_executable(davidsdk_images_viewer davidsdk_images_viewer.cpp) target_link_libraries(davidsdk_images_viewer ${PCL_LIBRARIES} ${OpenCV_LIBS}) diff --git a/doc/tutorials/content/sources/don_segmentation/CMakeLists.txt b/doc/tutorials/content/sources/don_segmentation/CMakeLists.txt index 3686b809..2afa6aaa 100644 --- a/doc/tutorials/content/sources/don_segmentation/CMakeLists.txt +++ b/doc/tutorials/content/sources/don_segmentation/CMakeLists.txt @@ -4,9 +4,5 @@ project(don_segmentation) find_package(PCL 1.7 REQUIRED) -include_directories(${PCL_INCLUDE_DIRS}) -link_directories(${PCL_LIBRARY_DIRS}) -add_definitions(${PCL_DEFINITIONS}) - add_executable (don_segmentation don_segmentation.cpp) target_link_libraries (don_segmentation ${PCL_LIBRARIES}) diff --git a/doc/tutorials/content/sources/ensenso_cameras/CMakeLists.txt b/doc/tutorials/content/sources/ensenso_cameras/CMakeLists.txt index c07d6f87..8d97ba7f 100644 --- a/doc/tutorials/content/sources/ensenso_cameras/CMakeLists.txt +++ b/doc/tutorials/content/sources/ensenso_cameras/CMakeLists.txt @@ -5,9 +5,5 @@ project(pcl-ensenso_cloud_images_viewer) find_package(PCL 1.8.0 REQUIRED) find_package(OpenCV REQUIRED) -include_directories(${PCL_INCLUDE_DIRS}) -link_directories(${PCL_LIBRARY_DIRS}) -add_definitions(${PCL_DEFINITIONS}) - add_executable(ensenso_cloud_images_viewer ensenso_cloud_images_viewer.cpp) target_link_libraries(ensenso_cloud_images_viewer ${PCL_LIBRARIES} ${OpenCV_LIBS}) diff --git a/doc/tutorials/content/sources/extract_indices/CMakeLists.txt b/doc/tutorials/content/sources/extract_indices/CMakeLists.txt index b9df2f73..705abe36 100644 --- a/doc/tutorials/content/sources/extract_indices/CMakeLists.txt +++ b/doc/tutorials/content/sources/extract_indices/CMakeLists.txt @@ -4,9 +4,5 @@ project(extract_indices) find_package(PCL 1.2 REQUIRED) -include_directories(${PCL_INCLUDE_DIRS}) -link_directories(${PCL_LIBRARY_DIRS}) -add_definitions(${PCL_DEFINITIONS}) - add_executable (extract_indices extract_indices.cpp) target_link_libraries (extract_indices ${PCL_LIBRARIES}) diff --git a/doc/tutorials/content/sources/function_filter/CMakeLists.txt b/doc/tutorials/content/sources/function_filter/CMakeLists.txt index 0e8e3d0f..3ce2f0c7 100644 --- a/doc/tutorials/content/sources/function_filter/CMakeLists.txt +++ b/doc/tutorials/content/sources/function_filter/CMakeLists.txt @@ -6,4 +6,3 @@ find_package(PCL 1.11.1.99 REQUIRED) add_executable (sphere_removal sphere_removal.cpp) target_link_libraries (sphere_removal ${PCL_LIBRARIES}) -add_definitions(${PCL_DEFINITIONS}) diff --git a/doc/tutorials/content/sources/global_hypothesis_verification/CMakeLists.txt b/doc/tutorials/content/sources/global_hypothesis_verification/CMakeLists.txt index d16b89d6..813bf3e9 100644 --- a/doc/tutorials/content/sources/global_hypothesis_verification/CMakeLists.txt +++ b/doc/tutorials/content/sources/global_hypothesis_verification/CMakeLists.txt @@ -5,9 +5,5 @@ project(global_hypothesis_verification) #Pcl find_package(PCL 1.7 REQUIRED) -include_directories(${PCL_INCLUDE_DIRS}) -link_directories(${PCL_LIBRARY_DIRS}) -add_definitions(${PCL_DEFINITIONS}) - add_executable (global_hypothesis_verification global_hypothesis_verification.cpp) target_link_libraries (global_hypothesis_verification ${PCL_LIBRARIES}) diff --git a/doc/tutorials/content/sources/gpu/people_detect/CMakeLists.txt b/doc/tutorials/content/sources/gpu/people_detect/CMakeLists.txt index 2b9a2447..6da89603 100644 --- a/doc/tutorials/content/sources/gpu/people_detect/CMakeLists.txt +++ b/doc/tutorials/content/sources/gpu/people_detect/CMakeLists.txt @@ -4,10 +4,6 @@ project(people_detect) find_package(PCL 1.7 REQUIRED) -include_directories(${PCL_INCLUDE_DIRS}) -link_directories(${PCL_LIBRARY_DIRS}) -add_definitions(${PCL_DEFINITIONS}) - #Searching CUDA find_package(CUDA) diff --git a/doc/tutorials/content/sources/greedy_projection/CMakeLists.txt b/doc/tutorials/content/sources/greedy_projection/CMakeLists.txt index 838a7fa0..b03b19f7 100644 --- a/doc/tutorials/content/sources/greedy_projection/CMakeLists.txt +++ b/doc/tutorials/content/sources/greedy_projection/CMakeLists.txt @@ -4,9 +4,5 @@ project(greedy_projection) find_package(PCL 1.2 REQUIRED) -include_directories(${PCL_INCLUDE_DIRS}) -link_directories(${PCL_LIBRARY_DIRS}) -add_definitions(${PCL_DEFINITIONS}) - add_executable (greedy_projection greedy_projection.cpp) target_link_libraries (greedy_projection ${PCL_LIBRARIES}) diff --git a/doc/tutorials/content/sources/ground_based_rgbd_people_detection/CMakeLists.txt b/doc/tutorials/content/sources/ground_based_rgbd_people_detection/CMakeLists.txt index 277aa610..08efb233 100644 --- a/doc/tutorials/content/sources/ground_based_rgbd_people_detection/CMakeLists.txt +++ b/doc/tutorials/content/sources/ground_based_rgbd_people_detection/CMakeLists.txt @@ -2,9 +2,5 @@ cmake_minimum_required(VERSION 3.5 FATAL_ERROR) project(ground_based_rgbd_people_detector) find_package(PCL 1.7 REQUIRED) -include_directories(${PCL_INCLUDE_DIRS}) -link_directories(${PCL_LIBRARY_DIRS}) -add_definitions(${PCL_DEFINITIONS}) - add_executable (ground_based_rgbd_people_detector MACOSX_BUNDLE src/main_ground_based_people_detection.cpp) target_link_libraries (ground_based_rgbd_people_detector ${PCL_LIBRARIES}) diff --git a/doc/tutorials/content/sources/iccv2011/CMakeLists.txt b/doc/tutorials/content/sources/iccv2011/CMakeLists.txt index 0d9251dd..139e414c 100644 --- a/doc/tutorials/content/sources/iccv2011/CMakeLists.txt +++ b/doc/tutorials/content/sources/iccv2011/CMakeLists.txt @@ -4,9 +4,7 @@ project(iccv11) find_package(PCL 1.5 REQUIRED) -include_directories(${PCL_INCLUDE_DIRS} include) -link_directories(${PCL_LIBRARY_DIRS}) -add_definitions(${PCL_DEFINITIONS}) +include_directories(include) add_executable (iccv2011_capture_tool src/capture_tool.cpp src/openni_capture.cpp) target_link_libraries (iccv2011_capture_tool ${PCL_LIBRARIES}) diff --git a/doc/tutorials/content/sources/implicit_shape_model/CMakeLists.txt b/doc/tutorials/content/sources/implicit_shape_model/CMakeLists.txt index 940e8ef1..22f85d11 100644 --- a/doc/tutorials/content/sources/implicit_shape_model/CMakeLists.txt +++ b/doc/tutorials/content/sources/implicit_shape_model/CMakeLists.txt @@ -5,9 +5,6 @@ project(implicit_shape_model) find_package(PCL 1.5 REQUIRED) set(CMAKE_BUILD_TYPE Release) -include_directories(${PCL_INCLUDE_DIRS}) -link_directories(${PCL_LIBRARY_DIRS}) -add_definitions(${PCL_DEFINITIONS}) add_executable (implicit_shape_model implicit_shape_model.cpp) target_link_libraries (implicit_shape_model ${PCL_LIBRARIES}) diff --git a/doc/tutorials/content/sources/interactive_icp/CMakeLists.txt b/doc/tutorials/content/sources/interactive_icp/CMakeLists.txt index 73ee09fd..44975832 100644 --- a/doc/tutorials/content/sources/interactive_icp/CMakeLists.txt +++ b/doc/tutorials/content/sources/interactive_icp/CMakeLists.txt @@ -4,9 +4,6 @@ project(pcl-interactive_icp) find_package(PCL 1.5 REQUIRED) -include_directories(${PCL_INCLUDE_DIRS}) -link_directories(${PCL_LIBRARY_DIRS}) -add_definitions(${PCL_DEFINITIONS}) add_executable (interactive_icp interactive_icp.cpp) target_link_libraries (interactive_icp ${PCL_LIBRARIES}) diff --git a/doc/tutorials/content/sources/iros2011/CMakeLists.txt b/doc/tutorials/content/sources/iros2011/CMakeLists.txt index c7bc9d58..2d969386 100644 --- a/doc/tutorials/content/sources/iros2011/CMakeLists.txt +++ b/doc/tutorials/content/sources/iros2011/CMakeLists.txt @@ -4,9 +4,7 @@ project(iros11) find_package(PCL 1.5 REQUIRED) -include_directories(${PCL_INCLUDE_DIRS} include) -link_directories(${PCL_LIBRARY_DIRS}) -add_definitions(${PCL_DEFINITIONS}) +include_directories(include) add_executable (iros2011_capture_tool src/capture_tool.cpp src/openni_capture.cpp) target_link_libraries (iros2011_capture_tool ${PCL_LIBRARIES}) diff --git a/doc/tutorials/content/sources/iterative_closest_point/CMakeLists.txt b/doc/tutorials/content/sources/iterative_closest_point/CMakeLists.txt index 447c725b..69ab08b7 100644 --- a/doc/tutorials/content/sources/iterative_closest_point/CMakeLists.txt +++ b/doc/tutorials/content/sources/iterative_closest_point/CMakeLists.txt @@ -4,10 +4,6 @@ project(iterative_closest_point) find_package(PCL 1.2 REQUIRED) -include_directories(${PCL_INCLUDE_DIRS}) -link_directories(${PCL_LIBRARY_DIRS}) -add_definitions(${PCL_DEFINITIONS}) - add_executable (iterative_closest_point iterative_closest_point.cpp) target_link_libraries (iterative_closest_point ${PCL_LIBRARIES}) diff --git a/doc/tutorials/content/sources/kdtree_search/CMakeLists.txt b/doc/tutorials/content/sources/kdtree_search/CMakeLists.txt index 4ed20c7d..3399218e 100644 --- a/doc/tutorials/content/sources/kdtree_search/CMakeLists.txt +++ b/doc/tutorials/content/sources/kdtree_search/CMakeLists.txt @@ -4,9 +4,5 @@ project(kdtree_search) find_package(PCL 1.2 REQUIRED) -include_directories(${PCL_INCLUDE_DIRS}) -link_directories(${PCL_LIBRARY_DIRS}) -add_definitions(${PCL_DEFINITIONS}) - add_executable (kdtree_search kdtree_search.cpp) target_link_libraries (kdtree_search ${PCL_LIBRARIES}) diff --git a/doc/tutorials/content/sources/matrix_transform/CMakeLists.txt b/doc/tutorials/content/sources/matrix_transform/CMakeLists.txt index 843ce41d..6279a543 100644 --- a/doc/tutorials/content/sources/matrix_transform/CMakeLists.txt +++ b/doc/tutorials/content/sources/matrix_transform/CMakeLists.txt @@ -4,9 +4,5 @@ project(pcl-matrix_transform) find_package(PCL 1.7 REQUIRED) -include_directories(${PCL_INCLUDE_DIRS}) -link_directories(${PCL_LIBRARY_DIRS}) -add_definitions(${PCL_DEFINITIONS}) - add_executable (matrix_transform matrix_transform.cpp) target_link_libraries (matrix_transform ${PCL_LIBRARIES}) diff --git a/doc/tutorials/content/sources/min_cut_segmentation/CMakeLists.txt b/doc/tutorials/content/sources/min_cut_segmentation/CMakeLists.txt index 2759751a..49fbafea 100644 --- a/doc/tutorials/content/sources/min_cut_segmentation/CMakeLists.txt +++ b/doc/tutorials/content/sources/min_cut_segmentation/CMakeLists.txt @@ -4,9 +4,5 @@ project(min_cut_segmentation) find_package(PCL 1.5 REQUIRED) -include_directories(${PCL_INCLUDE_DIRS}) -link_directories(${PCL_LIBRARY_DIRS}) -add_definitions(${PCL_DEFINITIONS}) - add_executable (min_cut_segmentation min_cut_segmentation.cpp) target_link_libraries (min_cut_segmentation ${PCL_LIBRARIES}) diff --git a/doc/tutorials/content/sources/model_outlier_removal/CMakeLists.txt b/doc/tutorials/content/sources/model_outlier_removal/CMakeLists.txt index 0dd90eeb..ea83239d 100644 --- a/doc/tutorials/content/sources/model_outlier_removal/CMakeLists.txt +++ b/doc/tutorials/content/sources/model_outlier_removal/CMakeLists.txt @@ -4,9 +4,5 @@ project(model_outlier_removal) find_package(PCL 1.7 REQUIRED) -include_directories(${PCL_INCLUDE_DIRS}) -link_directories(${PCL_LIBRARY_DIRS}) -add_definitions(${PCL_DEFINITIONS}) - add_executable (model_outlier_removal model_outlier_removal.cpp) target_link_libraries (model_outlier_removal ${PCL_LIBRARIES}) diff --git a/doc/tutorials/content/sources/moment_of_inertia/CMakeLists.txt b/doc/tutorials/content/sources/moment_of_inertia/CMakeLists.txt index 6891ea61..b1f30a29 100644 --- a/doc/tutorials/content/sources/moment_of_inertia/CMakeLists.txt +++ b/doc/tutorials/content/sources/moment_of_inertia/CMakeLists.txt @@ -4,10 +4,6 @@ project(moment_of_inertia) find_package(PCL 1.8 REQUIRED) -include_directories(${PCL_INCLUDE_DIRS}) -link_directories(${PCL_LIBRARY_DIRS}) -add_definitions(${PCL_DEFINITIONS}) - add_executable (moment_of_inertia moment_of_inertia.cpp) target_link_libraries (moment_of_inertia ${PCL_LIBRARIES}) diff --git a/doc/tutorials/content/sources/narf_descriptor_visualization/CMakeLists.txt b/doc/tutorials/content/sources/narf_descriptor_visualization/CMakeLists.txt index fd8b918e..3b89a421 100644 --- a/doc/tutorials/content/sources/narf_descriptor_visualization/CMakeLists.txt +++ b/doc/tutorials/content/sources/narf_descriptor_visualization/CMakeLists.txt @@ -4,9 +4,5 @@ project(narf_descriptor_visualization) find_package(PCL 1.3 REQUIRED) -include_directories(${PCL_INCLUDE_DIRS}) -link_directories(${PCL_LIBRARY_DIRS}) -add_definitions(${PCL_DEFINITIONS}) - add_executable (narf_descriptor_visualization narf_descriptor_visualization.cpp) target_link_libraries (narf_descriptor_visualization ${PCL_LIBRARIES}) diff --git a/doc/tutorials/content/sources/narf_feature_extraction/CMakeLists.txt b/doc/tutorials/content/sources/narf_feature_extraction/CMakeLists.txt index e9989a14..1589f62e 100644 --- a/doc/tutorials/content/sources/narf_feature_extraction/CMakeLists.txt +++ b/doc/tutorials/content/sources/narf_feature_extraction/CMakeLists.txt @@ -4,9 +4,5 @@ project(narf_feature_extraction) find_package(PCL 1.3 REQUIRED) -include_directories(${PCL_INCLUDE_DIRS}) -link_directories(${PCL_LIBRARY_DIRS}) -add_definitions(${PCL_DEFINITIONS}) - add_executable (narf_feature_extraction narf_feature_extraction.cpp) target_link_libraries (narf_feature_extraction ${PCL_LIBRARIES}) diff --git a/doc/tutorials/content/sources/narf_keypoint_extraction/CMakeLists.txt b/doc/tutorials/content/sources/narf_keypoint_extraction/CMakeLists.txt index a98c899b..98485a2b 100644 --- a/doc/tutorials/content/sources/narf_keypoint_extraction/CMakeLists.txt +++ b/doc/tutorials/content/sources/narf_keypoint_extraction/CMakeLists.txt @@ -4,9 +4,5 @@ project(narf_keypoint_extraction) find_package(PCL 1.3 REQUIRED) -include_directories(${PCL_INCLUDE_DIRS}) -link_directories(${PCL_LIBRARY_DIRS}) -add_definitions(${PCL_DEFINITIONS}) - add_executable (narf_keypoint_extraction narf_keypoint_extraction.cpp) target_link_libraries (narf_keypoint_extraction ${PCL_LIBRARIES}) diff --git a/doc/tutorials/content/sources/normal_distributions_transform/CMakeLists.txt b/doc/tutorials/content/sources/normal_distributions_transform/CMakeLists.txt index 6f98b3dc..3065f883 100644 --- a/doc/tutorials/content/sources/normal_distributions_transform/CMakeLists.txt +++ b/doc/tutorials/content/sources/normal_distributions_transform/CMakeLists.txt @@ -4,10 +4,6 @@ project(normal_distributions_transform) find_package(PCL 1.5 REQUIRED) -include_directories(${PCL_INCLUDE_DIRS}) -link_directories(${PCL_LIBRARY_DIRS}) -add_definitions(${PCL_DEFINITIONS}) - add_executable(normal_distributions_transform normal_distributions_transform.cpp) target_link_libraries (normal_distributions_transform ${PCL_LIBRARIES}) diff --git a/doc/tutorials/content/sources/normal_estimation_using_integral_images/CMakeLists.txt b/doc/tutorials/content/sources/normal_estimation_using_integral_images/CMakeLists.txt index 2733ee14..740fe0bb 100644 --- a/doc/tutorials/content/sources/normal_estimation_using_integral_images/CMakeLists.txt +++ b/doc/tutorials/content/sources/normal_estimation_using_integral_images/CMakeLists.txt @@ -4,10 +4,6 @@ project(normal_estimation_using_integral_images) find_package(PCL 1.3 REQUIRED) -include_directories(${PCL_INCLUDE_DIRS}) -link_directories(${PCL_LIBRARY_DIRS}) -add_definitions(${PCL_DEFINITIONS}) - add_executable (normal_estimation_using_integral_images normal_estimation_using_integral_images.cpp) target_link_libraries (normal_estimation_using_integral_images ${PCL_LIBRARIES}) diff --git a/doc/tutorials/content/sources/octree_change_detection/CMakeLists.txt b/doc/tutorials/content/sources/octree_change_detection/CMakeLists.txt index a7bf4bb6..bda05b5a 100644 --- a/doc/tutorials/content/sources/octree_change_detection/CMakeLists.txt +++ b/doc/tutorials/content/sources/octree_change_detection/CMakeLists.txt @@ -4,9 +4,5 @@ project(octree_change_detection) find_package(PCL 1.2 REQUIRED) -include_directories(${PCL_INCLUDE_DIRS}) -link_directories(${PCL_LIBRARY_DIRS}) -add_definitions(${PCL_DEFINITIONS}) - add_executable (octree_change_detection octree_change_detection.cpp) target_link_libraries (octree_change_detection ${PCL_LIBRARIES}) diff --git a/doc/tutorials/content/sources/octree_search/CMakeLists.txt b/doc/tutorials/content/sources/octree_search/CMakeLists.txt index 80e7c785..63dcc342 100644 --- a/doc/tutorials/content/sources/octree_search/CMakeLists.txt +++ b/doc/tutorials/content/sources/octree_search/CMakeLists.txt @@ -4,9 +4,5 @@ project(octree_search) find_package(PCL 1.2 REQUIRED) -include_directories(${PCL_INCLUDE_DIRS}) -link_directories(${PCL_LIBRARY_DIRS}) -add_definitions(${PCL_DEFINITIONS}) - add_executable (octree_search octree_search.cpp) target_link_libraries (octree_search ${PCL_LIBRARIES}) diff --git a/doc/tutorials/content/sources/openni_grabber/CMakeLists.txt b/doc/tutorials/content/sources/openni_grabber/CMakeLists.txt index c0ff398c..bfbe767a 100644 --- a/doc/tutorials/content/sources/openni_grabber/CMakeLists.txt +++ b/doc/tutorials/content/sources/openni_grabber/CMakeLists.txt @@ -4,9 +4,5 @@ project(openni_grabber) find_package(PCL 1.2 REQUIRED) -include_directories(${PCL_INCLUDE_DIRS}) -link_directories(${PCL_LIBRARY_DIRS}) -add_definitions(${PCL_DEFINITIONS}) - add_executable (openni_grabber openni_grabber.cpp) target_link_libraries (openni_grabber ${PCL_LIBRARIES}) diff --git a/doc/tutorials/content/sources/openni_narf_keypoint_extraction/CMakeLists.txt b/doc/tutorials/content/sources/openni_narf_keypoint_extraction/CMakeLists.txt index 7a4d2486..f7a7b63e 100644 --- a/doc/tutorials/content/sources/openni_narf_keypoint_extraction/CMakeLists.txt +++ b/doc/tutorials/content/sources/openni_narf_keypoint_extraction/CMakeLists.txt @@ -4,10 +4,6 @@ project(openni_narf_keypoint_extraction) find_package(PCL 1.3 REQUIRED) -include_directories(${PCL_INCLUDE_DIRS}) -link_directories(${PCL_LIBRARY_DIRS}) -add_definitions(${PCL_DEFINITIONS}) - add_executable (openni_narf_keypoint_extraction openni_narf_keypoint_extraction.cpp) target_link_libraries (openni_narf_keypoint_extraction ${PCL_LIBRARIES}) diff --git a/doc/tutorials/content/sources/openni_range_image_visualization/CMakeLists.txt b/doc/tutorials/content/sources/openni_range_image_visualization/CMakeLists.txt index 7b247d89..f0a4fb0c 100644 --- a/doc/tutorials/content/sources/openni_range_image_visualization/CMakeLists.txt +++ b/doc/tutorials/content/sources/openni_range_image_visualization/CMakeLists.txt @@ -4,9 +4,5 @@ project(openni_range_image_visualization) find_package(PCL 1.3 REQUIRED) -include_directories(${PCL_INCLUDE_DIRS}) -link_directories(${PCL_LIBRARY_DIRS}) -add_definitions(${PCL_DEFINITIONS}) - add_executable (openni_range_image_visualization openni_range_image_visualization.cpp) target_link_libraries (openni_range_image_visualization ${PCL_LIBRARIES}) diff --git a/doc/tutorials/content/sources/pairwise_incremental_registration/CMakeLists.txt b/doc/tutorials/content/sources/pairwise_incremental_registration/CMakeLists.txt index da6563df..b387662a 100644 --- a/doc/tutorials/content/sources/pairwise_incremental_registration/CMakeLists.txt +++ b/doc/tutorials/content/sources/pairwise_incremental_registration/CMakeLists.txt @@ -4,9 +4,5 @@ project(tuto-pairwise) find_package(PCL 1.4 REQUIRED) -include_directories(${PCL_INCLUDE_DIRS}) -link_directories(${PCL_LIBRARY_DIRS}) -add_definitions(${PCL_DEFINITIONS}) - add_executable (pairwise_incremental_registration pairwise_incremental_registration.cpp) target_link_libraries (pairwise_incremental_registration ${PCL_LIBRARIES}) diff --git a/doc/tutorials/content/sources/passthrough/CMakeLists.txt b/doc/tutorials/content/sources/passthrough/CMakeLists.txt index f0576845..ffe8dec3 100644 --- a/doc/tutorials/content/sources/passthrough/CMakeLists.txt +++ b/doc/tutorials/content/sources/passthrough/CMakeLists.txt @@ -4,9 +4,5 @@ project(passthrough) find_package(PCL 1.2 REQUIRED) -include_directories(${PCL_INCLUDE_DIRS}) -link_directories(${PCL_LIBRARY_DIRS}) -add_definitions(${PCL_DEFINITIONS}) - add_executable (passthrough passthrough.cpp) target_link_libraries (passthrough ${PCL_LIBRARIES}) diff --git a/doc/tutorials/content/sources/pcd_read/CMakeLists.txt b/doc/tutorials/content/sources/pcd_read/CMakeLists.txt index af4ad3d4..26450f38 100644 --- a/doc/tutorials/content/sources/pcd_read/CMakeLists.txt +++ b/doc/tutorials/content/sources/pcd_read/CMakeLists.txt @@ -4,9 +4,5 @@ project(pcd_read) find_package(PCL 1.2 REQUIRED) -include_directories(${PCL_INCLUDE_DIRS}) -link_directories(${PCL_LIBRARY_DIRS}) -add_definitions(${PCL_DEFINITIONS}) - add_executable (pcd_read pcd_read.cpp) target_link_libraries (pcd_read ${PCL_LIBRARIES}) diff --git a/doc/tutorials/content/sources/pcd_write/CMakeLists.txt b/doc/tutorials/content/sources/pcd_write/CMakeLists.txt index 9fe83623..0e71ad6e 100644 --- a/doc/tutorials/content/sources/pcd_write/CMakeLists.txt +++ b/doc/tutorials/content/sources/pcd_write/CMakeLists.txt @@ -4,9 +4,5 @@ project(pcd_write) find_package(PCL 1.2 REQUIRED) -include_directories(${PCL_INCLUDE_DIRS}) -link_directories(${PCL_LIBRARY_DIRS}) -add_definitions(${PCL_DEFINITIONS}) - add_executable (pcd_write pcd_write.cpp) target_link_libraries (pcd_write ${PCL_LIBRARIES}) diff --git a/doc/tutorials/content/sources/pcl_painter2D/CMakeLists.txt b/doc/tutorials/content/sources/pcl_painter2D/CMakeLists.txt index 1385f46c..1d536718 100644 --- a/doc/tutorials/content/sources/pcl_painter2D/CMakeLists.txt +++ b/doc/tutorials/content/sources/pcl_painter2D/CMakeLists.txt @@ -1,8 +1,5 @@ cmake_minimum_required(VERSION 3.5 FATAL_ERROR) project(pcl_painter2D_demo) find_package(PCL 1.7) -include_directories(${PCL_INCLUDE_DIRS}) -link_directories(${PCL_LIBRARY_DIRS}) -add_definitions(${PCL_DEFINITIONS}) add_executable(pcl_painter2D_demo pcl_painter2D_demo.cpp) target_link_libraries(pcl_painter2D_demo ${PCL_LIBRARIES}) diff --git a/doc/tutorials/content/sources/pcl_plotter/CMakeLists.txt b/doc/tutorials/content/sources/pcl_plotter/CMakeLists.txt index 404e5ebd..547bca82 100644 --- a/doc/tutorials/content/sources/pcl_plotter/CMakeLists.txt +++ b/doc/tutorials/content/sources/pcl_plotter/CMakeLists.txt @@ -1,8 +1,5 @@ cmake_minimum_required(VERSION 3.5 FATAL_ERROR) project(pcl_plotter) find_package(PCL 1.7 REQUIRED COMPONENTS common visualization) -include_directories(${PCL_INCLUDE_DIRS}) -link_directories(${PCL_LIBRARY_DIRS}) -add_definitions(${PCL_DEFINITIONS}) add_executable(pcl_plotter pcl_plotter_demo.cpp) target_link_libraries(pcl_plotter ${PCL_LIBRARIES}) diff --git a/doc/tutorials/content/sources/pcl_visualizer/CMakeLists.txt b/doc/tutorials/content/sources/pcl_visualizer/CMakeLists.txt index b6b2d52c..971406d2 100644 --- a/doc/tutorials/content/sources/pcl_visualizer/CMakeLists.txt +++ b/doc/tutorials/content/sources/pcl_visualizer/CMakeLists.txt @@ -4,9 +4,5 @@ project(pcl_visualizer_viewports) find_package(PCL 1.2 REQUIRED) -include_directories(${PCL_INCLUDE_DIRS}) -link_directories(${PCL_LIBRARY_DIRS}) -add_definitions(${PCL_DEFINITIONS}) - add_executable (pcl_visualizer_demo pcl_visualizer_demo.cpp) target_link_libraries (pcl_visualizer_demo ${PCL_LIBRARIES}) diff --git a/doc/tutorials/content/sources/planar_segmentation/CMakeLists.txt b/doc/tutorials/content/sources/planar_segmentation/CMakeLists.txt index bb638d5f..bf66bfa5 100644 --- a/doc/tutorials/content/sources/planar_segmentation/CMakeLists.txt +++ b/doc/tutorials/content/sources/planar_segmentation/CMakeLists.txt @@ -4,9 +4,5 @@ project(planar_segmentation) find_package(PCL 1.2 REQUIRED) -include_directories(${PCL_INCLUDE_DIRS}) -link_directories(${PCL_LIBRARY_DIRS}) -add_definitions(${PCL_DEFINITIONS}) - add_executable (planar_segmentation planar_segmentation.cpp) target_link_libraries (planar_segmentation ${PCL_LIBRARIES}) diff --git a/doc/tutorials/content/sources/point_cloud_compression/CMakeLists.txt b/doc/tutorials/content/sources/point_cloud_compression/CMakeLists.txt index 5d2c6899..ad0731e3 100644 --- a/doc/tutorials/content/sources/point_cloud_compression/CMakeLists.txt +++ b/doc/tutorials/content/sources/point_cloud_compression/CMakeLists.txt @@ -4,9 +4,5 @@ project(point_cloud_compression) find_package(PCL 1.2 REQUIRED) -include_directories(${PCL_INCLUDE_DIRS}) -link_directories(${PCL_LIBRARY_DIRS}) -add_definitions(${PCL_DEFINITIONS}) - add_executable (point_cloud_compression point_cloud_compression.cpp) target_link_libraries (point_cloud_compression ${PCL_LIBRARIES}) diff --git a/doc/tutorials/content/sources/project_inliers/CMakeLists.txt b/doc/tutorials/content/sources/project_inliers/CMakeLists.txt index 2c0be2f1..2a7ec2b5 100644 --- a/doc/tutorials/content/sources/project_inliers/CMakeLists.txt +++ b/doc/tutorials/content/sources/project_inliers/CMakeLists.txt @@ -4,9 +4,5 @@ project(project_inliers) find_package(PCL 1.2 REQUIRED) -include_directories(${PCL_INCLUDE_DIRS}) -link_directories(${PCL_LIBRARY_DIRS}) -add_definitions(${PCL_DEFINITIONS}) - add_executable (project_inliers project_inliers.cpp) target_link_libraries (project_inliers ${PCL_LIBRARIES}) diff --git a/doc/tutorials/content/sources/qt_colorize_cloud/CMakeLists.txt b/doc/tutorials/content/sources/qt_colorize_cloud/CMakeLists.txt index 221da6fe..119da3cb 100644 --- a/doc/tutorials/content/sources/qt_colorize_cloud/CMakeLists.txt +++ b/doc/tutorials/content/sources/qt_colorize_cloud/CMakeLists.txt @@ -25,9 +25,6 @@ find_package(PCL 1.7.1 REQUIRED) # Fix a compilation bug under ubuntu 16.04 (Xenial) list(REMOVE_ITEM PCL_LIBRARIES "vtkproj4") -include_directories(${PCL_INCLUDE_DIRS}) -add_definitions(${PCL_DEFINITIONS}) - set(project_SOURCES main.cpp pclviewer.cpp) add_executable(${PROJECT_NAME} ${project_SOURCES}) diff --git a/doc/tutorials/content/sources/qt_visualizer/CMakeLists.txt b/doc/tutorials/content/sources/qt_visualizer/CMakeLists.txt index 96580a19..2af6ccb0 100644 --- a/doc/tutorials/content/sources/qt_visualizer/CMakeLists.txt +++ b/doc/tutorials/content/sources/qt_visualizer/CMakeLists.txt @@ -25,9 +25,6 @@ find_package(PCL 1.7.1 REQUIRED) # Fix a compilation bug under ubuntu 16.04 (Xenial) list(REMOVE_ITEM PCL_LIBRARIES "vtkproj4") -include_directories(${PCL_INCLUDE_DIRS}) -add_definitions(${PCL_DEFINITIONS}) - set(project_SOURCES main.cpp pclviewer.cpp) add_executable(${PROJECT_NAME} ${project_SOURCES}) diff --git a/doc/tutorials/content/sources/radius_outlier_removal/CMakeLists.txt b/doc/tutorials/content/sources/radius_outlier_removal/CMakeLists.txt index b1236295..15ea32e1 100644 --- a/doc/tutorials/content/sources/radius_outlier_removal/CMakeLists.txt +++ b/doc/tutorials/content/sources/radius_outlier_removal/CMakeLists.txt @@ -4,9 +4,5 @@ project(radius_outlier_removal) find_package(PCL 1.2 REQUIRED) -include_directories(${PCL_INCLUDE_DIRS}) -link_directories(${PCL_LIBRARY_DIRS}) -add_definitions(${PCL_DEFINITIONS}) - add_executable (radius_outlier_removal radius_outlier_removal.cpp) target_link_libraries (radius_outlier_removal ${PCL_LIBRARIES}) diff --git a/doc/tutorials/content/sources/random_sample_consensus/CMakeLists.txt b/doc/tutorials/content/sources/random_sample_consensus/CMakeLists.txt index 9d547639..1760aa22 100644 --- a/doc/tutorials/content/sources/random_sample_consensus/CMakeLists.txt +++ b/doc/tutorials/content/sources/random_sample_consensus/CMakeLists.txt @@ -4,9 +4,5 @@ project(random_sample_consensus) find_package(PCL 1.2 REQUIRED) -include_directories(${PCL_INCLUDE_DIRS}) -link_directories(${PCL_LIBRARY_DIRS}) -add_definitions(${PCL_DEFINITIONS}) - add_executable (random_sample_consensus random_sample_consensus.cpp) target_link_libraries (random_sample_consensus ${PCL_LIBRARIES}) diff --git a/doc/tutorials/content/sources/range_image_border_extraction/CMakeLists.txt b/doc/tutorials/content/sources/range_image_border_extraction/CMakeLists.txt index 348ed47a..abd6c680 100644 --- a/doc/tutorials/content/sources/range_image_border_extraction/CMakeLists.txt +++ b/doc/tutorials/content/sources/range_image_border_extraction/CMakeLists.txt @@ -4,10 +4,6 @@ project(range_image_border_extraction) find_package(PCL 1.3 REQUIRED) -include_directories(${PCL_INCLUDE_DIRS}) -link_directories(${PCL_LIBRARY_DIRS}) -add_definitions(${PCL_DEFINITIONS}) - add_executable (range_image_border_extraction range_image_border_extraction.cpp) target_link_libraries (range_image_border_extraction ${PCL_LIBRARIES}) diff --git a/doc/tutorials/content/sources/range_image_creation/CMakeLists.txt b/doc/tutorials/content/sources/range_image_creation/CMakeLists.txt index 91f2a365..dc093687 100644 --- a/doc/tutorials/content/sources/range_image_creation/CMakeLists.txt +++ b/doc/tutorials/content/sources/range_image_creation/CMakeLists.txt @@ -4,9 +4,5 @@ project(range_image_creation) find_package(PCL 1.2 REQUIRED) -include_directories(${PCL_INCLUDE_DIRS}) -link_directories(${PCL_LIBRARY_DIRS}) -add_definitions(${PCL_DEFINITIONS}) - add_executable (range_image_creation range_image_creation.cpp) target_link_libraries (range_image_creation ${PCL_LIBRARIES}) diff --git a/doc/tutorials/content/sources/range_image_visualization/CMakeLists.txt b/doc/tutorials/content/sources/range_image_visualization/CMakeLists.txt index dc82165f..360c0781 100644 --- a/doc/tutorials/content/sources/range_image_visualization/CMakeLists.txt +++ b/doc/tutorials/content/sources/range_image_visualization/CMakeLists.txt @@ -4,10 +4,6 @@ project(range_image_visualization) find_package(PCL 1.3 REQUIRED) -include_directories(${PCL_INCLUDE_DIRS}) -link_directories(${PCL_LIBRARY_DIRS}) -add_definitions(${PCL_DEFINITIONS}) - add_executable (range_image_visualization range_image_visualization.cpp) target_link_libraries (range_image_visualization ${PCL_LIBRARIES}) diff --git a/doc/tutorials/content/sources/region_growing_rgb_segmentation/CMakeLists.txt b/doc/tutorials/content/sources/region_growing_rgb_segmentation/CMakeLists.txt index 2ea126e9..b48cc066 100644 --- a/doc/tutorials/content/sources/region_growing_rgb_segmentation/CMakeLists.txt +++ b/doc/tutorials/content/sources/region_growing_rgb_segmentation/CMakeLists.txt @@ -4,10 +4,6 @@ project(region_growing_rgb_segmentation) find_package(PCL 1.5 REQUIRED) -include_directories(${PCL_INCLUDE_DIRS}) -link_directories(${PCL_LIBRARY_DIRS}) -add_definitions(${PCL_DEFINITIONS}) - add_executable (region_growing_rgb_segmentation region_growing_rgb_segmentation.cpp) target_link_libraries (region_growing_rgb_segmentation ${PCL_LIBRARIES}) diff --git a/doc/tutorials/content/sources/region_growing_segmentation/CMakeLists.txt b/doc/tutorials/content/sources/region_growing_segmentation/CMakeLists.txt index 8b410b89..6b2d19a3 100644 --- a/doc/tutorials/content/sources/region_growing_segmentation/CMakeLists.txt +++ b/doc/tutorials/content/sources/region_growing_segmentation/CMakeLists.txt @@ -4,10 +4,6 @@ project(region_growing_segmentation) find_package(PCL 1.5 REQUIRED) -include_directories(${PCL_INCLUDE_DIRS}) -link_directories(${PCL_LIBRARY_DIRS}) -add_definitions(${PCL_DEFINITIONS}) - add_executable (region_growing_segmentation region_growing_segmentation.cpp) target_link_libraries (region_growing_segmentation ${PCL_LIBRARIES}) diff --git a/doc/tutorials/content/sources/registration_api/CMakeLists.txt b/doc/tutorials/content/sources/registration_api/CMakeLists.txt index 152e0cca..abdfdbb5 100644 --- a/doc/tutorials/content/sources/registration_api/CMakeLists.txt +++ b/doc/tutorials/content/sources/registration_api/CMakeLists.txt @@ -4,10 +4,6 @@ project(registration_api) find_package(PCL 1.3 REQUIRED) -include_directories(${PCL_INCLUDE_DIRS}) -link_directories(${PCL_LIBRARY_DIRS}) -add_definitions(${PCL_DEFINITIONS}) - #add_executable (example1 example1.cpp) #target_link_libraries (example1 ${PCL_LIBRARIES}) diff --git a/doc/tutorials/content/sources/remove_outliers/CMakeLists.txt b/doc/tutorials/content/sources/remove_outliers/CMakeLists.txt index f9e524f3..575e23ea 100644 --- a/doc/tutorials/content/sources/remove_outliers/CMakeLists.txt +++ b/doc/tutorials/content/sources/remove_outliers/CMakeLists.txt @@ -4,9 +4,5 @@ project(remove_outliers) find_package(PCL 1.2 REQUIRED) -include_directories(${PCL_INCLUDE_DIRS}) -link_directories(${PCL_LIBRARY_DIRS}) -add_definitions(${PCL_DEFINITIONS}) - add_executable (remove_outliers remove_outliers.cpp) target_link_libraries (remove_outliers ${PCL_LIBRARIES}) diff --git a/doc/tutorials/content/sources/resampling/CMakeLists.txt b/doc/tutorials/content/sources/resampling/CMakeLists.txt index fed55d82..879de630 100644 --- a/doc/tutorials/content/sources/resampling/CMakeLists.txt +++ b/doc/tutorials/content/sources/resampling/CMakeLists.txt @@ -4,9 +4,5 @@ project(resampling) find_package(PCL 1.2 REQUIRED) -include_directories(${PCL_INCLUDE_DIRS}) -link_directories(${PCL_LIBRARY_DIRS}) -add_definitions(${PCL_DEFINITIONS}) - add_executable (resampling resampling.cpp) target_link_libraries (resampling ${PCL_LIBRARIES}) diff --git a/doc/tutorials/content/sources/rops_feature/CMakeLists.txt b/doc/tutorials/content/sources/rops_feature/CMakeLists.txt index 8fb6ce91..9e09ea9f 100644 --- a/doc/tutorials/content/sources/rops_feature/CMakeLists.txt +++ b/doc/tutorials/content/sources/rops_feature/CMakeLists.txt @@ -4,10 +4,6 @@ project(rops_feature) find_package(PCL 1.8 REQUIRED) -include_directories(${PCL_INCLUDE_DIRS}) -link_directories(${PCL_LIBRARY_DIRS}) -add_definitions(${PCL_DEFINITIONS}) - add_executable (rops_feature rops_feature.cpp) target_link_libraries (rops_feature ${PCL_LIBRARIES}) diff --git a/doc/tutorials/content/sources/statistical_removal/CMakeLists.txt b/doc/tutorials/content/sources/statistical_removal/CMakeLists.txt index 04c4fb28..480c5a31 100644 --- a/doc/tutorials/content/sources/statistical_removal/CMakeLists.txt +++ b/doc/tutorials/content/sources/statistical_removal/CMakeLists.txt @@ -4,9 +4,5 @@ project(statistical_removal) find_package(PCL 1.2 REQUIRED) -include_directories(${PCL_INCLUDE_DIRS}) -link_directories(${PCL_LIBRARY_DIRS}) -add_definitions(${PCL_DEFINITIONS}) - add_executable (statistical_removal statistical_removal.cpp) target_link_libraries (statistical_removal ${PCL_LIBRARIES}) diff --git a/doc/tutorials/content/sources/stick_segmentation/CMakeLists.txt b/doc/tutorials/content/sources/stick_segmentation/CMakeLists.txt index dd6fc63b..f34601d8 100644 --- a/doc/tutorials/content/sources/stick_segmentation/CMakeLists.txt +++ b/doc/tutorials/content/sources/stick_segmentation/CMakeLists.txt @@ -4,9 +4,5 @@ project(stick_segmentation) find_package(PCL 1.2 REQUIRED) -include_directories(${PCL_INCLUDE_DIRS}) -link_directories(${PCL_LIBRARY_DIRS}) -add_definitions(${PCL_DEFINITIONS}) - add_executable (stick_segmentation stick_segmentation.cpp) target_link_libraries (stick_segmentation ${PCL_LIBRARIES}) diff --git a/doc/tutorials/content/sources/supervoxel_clustering/CMakeLists.txt b/doc/tutorials/content/sources/supervoxel_clustering/CMakeLists.txt index f1e758fd..a52b2914 100644 --- a/doc/tutorials/content/sources/supervoxel_clustering/CMakeLists.txt +++ b/doc/tutorials/content/sources/supervoxel_clustering/CMakeLists.txt @@ -4,9 +4,5 @@ project(supervoxel_clustering) find_package(PCL 1.8 REQUIRED) -include_directories(${PCL_INCLUDE_DIRS}) -link_directories(${PCL_LIBRARY_DIRS}) -add_definitions(${PCL_DEFINITIONS}) - add_executable (supervoxel_clustering supervoxel_clustering.cpp) target_link_libraries (supervoxel_clustering ${PCL_LIBRARIES}) diff --git a/doc/tutorials/content/sources/template_alignment/CMakeLists.txt b/doc/tutorials/content/sources/template_alignment/CMakeLists.txt index 6044f411..03b8e5bc 100644 --- a/doc/tutorials/content/sources/template_alignment/CMakeLists.txt +++ b/doc/tutorials/content/sources/template_alignment/CMakeLists.txt @@ -4,9 +4,5 @@ project(template_alignment) find_package(PCL 1.2 REQUIRED) -include_directories(${PCL_INCLUDE_DIRS}) -link_directories(${PCL_LIBRARY_DIRS}) -add_definitions(${PCL_DEFINITIONS}) - add_executable (template_alignment template_alignment.cpp) target_link_libraries (template_alignment ${PCL_LIBRARIES}) diff --git a/doc/tutorials/content/sources/tracking/CMakeLists.txt b/doc/tutorials/content/sources/tracking/CMakeLists.txt index 4e60a9ce..a0a97d90 100644 --- a/doc/tutorials/content/sources/tracking/CMakeLists.txt +++ b/doc/tutorials/content/sources/tracking/CMakeLists.txt @@ -4,9 +4,5 @@ project(openni_tracking) find_package(PCL 1.7 REQUIRED) -include_directories(${PCL_INCLUDE_DIRS}) -link_directories(${PCL_LIBRARY_DIRS}) -add_definitions(${PCL_DEFINITIONS}) - add_executable (tracking_sample tracking_sample.cpp) target_link_libraries (tracking_sample ${PCL_LIBRARIES}) diff --git a/doc/tutorials/content/sources/vfh_recognition/CMakeLists.txt b/doc/tutorials/content/sources/vfh_recognition/CMakeLists.txt index 7c4a9f1f..66afee3f 100644 --- a/doc/tutorials/content/sources/vfh_recognition/CMakeLists.txt +++ b/doc/tutorials/content/sources/vfh_recognition/CMakeLists.txt @@ -3,9 +3,6 @@ cmake_minimum_required(VERSION 3.5 FATAL_ERROR) project(vfh_cluster_classifier) find_package(PCL 1.2 REQUIRED) -include_directories(${PCL_INCLUDE_DIRS}) -link_directories(${PCL_LIBRARY_DIRS}) -add_definitions(${PCL_DEFINITIONS}) find_package(HDF5 REQUIRED) find_package(FLANN REQUIRED) diff --git a/doc/tutorials/content/sources/voxel_grid/CMakeLists.txt b/doc/tutorials/content/sources/voxel_grid/CMakeLists.txt index e99999de..65fd580b 100644 --- a/doc/tutorials/content/sources/voxel_grid/CMakeLists.txt +++ b/doc/tutorials/content/sources/voxel_grid/CMakeLists.txt @@ -4,9 +4,5 @@ project(voxel_grid) find_package(PCL 1.2 REQUIRED) -include_directories(${PCL_INCLUDE_DIRS}) -link_directories(${PCL_LIBRARY_DIRS}) -add_definitions(${PCL_DEFINITIONS}) - add_executable (voxel_grid voxel_grid.cpp) target_link_libraries (voxel_grid ${PCL_LIBRARIES}) diff --git a/doc/tutorials/content/using_pcl_pcl_config.rst b/doc/tutorials/content/using_pcl_pcl_config.rst index ae3fe9a1..5248c225 100644 --- a/doc/tutorials/content/using_pcl_pcl_config.rst +++ b/doc/tutorials/content/using_pcl_pcl_config.rst @@ -21,12 +21,9 @@ CMakeLists.txt that contains: .. code-block:: cmake - cmake_minimum_required(VERSION 2.6 FATAL_ERROR) + cmake_minimum_required(VERSION 3.10 FATAL_ERROR) project(MY_GRAND_PROJECT) find_package(PCL 1.3 REQUIRED) - include_directories(${PCL_INCLUDE_DIRS}) - link_directories(${PCL_LIBRARY_DIRS}) - add_definitions(${PCL_DEFINITIONS}) add_executable(pcd_write_test pcd_write.cpp) target_link_libraries(pcd_write_test ${PCL_LIBRARIES}) @@ -37,7 +34,7 @@ Now, let's see what we did. .. code-block:: cmake - cmake_minimum_required(VERSION 2.6 FATAL_ERROR) + cmake_minimum_required(VERSION 3.10 FATAL_ERROR) This is mandatory for cmake, and since we are making a very basic project we don't need features from cmake 2.8 or higher. @@ -63,29 +60,6 @@ gracefully if it can't be found. As PCL is modular one can request: * several: find_package(PCL 1.3 REQUIRED COMPONENTS io common) * all existing: find_package(PCL 1.3 REQUIRED) -.. code-block:: cmake - - include_directories(${PCL_INCLUDE_DIRS}) - link_directories(${PCL_LIBRARY_DIRS}) - add_definitions(${PCL_DEFINITIONS}) - -When PCL is found, several related variables are set: - -* `PCL_FOUND`: set to 1 if PCL is found, otherwise unset -* `PCL_INCLUDE_DIRS`: set to the paths to PCL installed headers and - the dependency headers -* `PCL_LIBRARIES`: set to the file names of the built and installed PCL libraries -* `PCL_LIBRARY_DIRS`: set to the paths to where PCL libraries and 3rd - party dependencies reside -* `PCL_VERSION`: the version of the found PCL -* `PCL_COMPONENTS`: lists all available components -* `PCL_DEFINITIONS`: lists the needed preprocessor definitions and compiler flags - -To let cmake know about external headers you include in your project, -one needs to use ``include_directories()`` macro. In our case -``PCL_INCLUDE_DIRS``, contains exactly what we need, thus we ask cmake -to search the paths it contains for a header potentially included. - .. code-block:: cmake add_executable(pcd_write_test pcd_write.cpp) @@ -111,6 +85,23 @@ allows for using others' projects targets as if you built them yourself. When you are using such targets they are called `imported targets` and act just like any other target. +CMake variables defined after finding PCL +========================================= + +When PCL is found, several related variables are set: + +* `PCL_FOUND`: set to 1 if PCL is found, otherwise unset +* `PCL_INCLUDE_DIRS`: set to the paths to PCL installed headers and + the dependency headers +* `PCL_LIBRARIES`: set to the file names of the built and installed PCL libraries +* `PCL_LIBRARY_DIRS`: set to the paths to where PCL libraries and 3rd + party dependencies reside +* `PCL_VERSION`: the version of the found PCL +* `PCL_COMPONENTS`: lists all available components +* `PCL_DEFINITIONS`: lists the needed preprocessor definitions and compiler flags + +In older PCL versions, it was necessary to explicitly tell CMake about `PCL_INCLUDE_DIRS`, `PCL_LIBRARY_DIRS`, and `PCL_DEFINITIONS`, but in newer PCL versions, the `target_link_libraries` call handles that automatically. + Compiling and running the project --------------------------------- diff --git a/examples/stereo/example_stereo_baseline.cpp b/examples/stereo/example_stereo_baseline.cpp index bf21c6f8..594ab246 100644 --- a/examples/stereo/example_stereo_baseline.cpp +++ b/examples/stereo/example_stereo_baseline.cpp @@ -1,3 +1,4 @@ +#include #include #include diff --git a/features/CMakeLists.txt b/features/CMakeLists.txt index f0a565eb..a2a04a42 100644 --- a/features/CMakeLists.txt +++ b/features/CMakeLists.txt @@ -114,7 +114,13 @@ set(impl_incs "include/pcl/${SUBSYS_NAME}/impl/range_image_border_extractor.hpp" ) +# The cpp files have been ordered so that files with a long compile time appear at the top, to efficiently build in parallel. Do not reorder alphabetically! set(srcs + src/integral_image_normal.cpp + src/shot.cpp + src/3dsc.cpp + src/multiscale_feature_persistence.cpp + src/vfh.cpp src/board.cpp src/flare.cpp src/brisk_2d.cpp @@ -128,20 +134,17 @@ set(srcs src/from_meshes.cpp src/gasd.cpp src/gfpfh.cpp - src/integral_image_normal.cpp src/intensity_gradient.cpp src/intensity_spin.cpp src/linear_least_squares_normal.cpp src/moment_invariants.cpp src/moment_of_inertia_estimation.cpp - src/multiscale_feature_persistence.cpp src/narf.cpp src/normal_3d.cpp src/normal_based_signature.cpp src/organized_edge_detection.cpp src/pfh.cpp src/ppf.cpp - src/shot.cpp src/shot_lrf.cpp src/spin_image.cpp src/principal_curvatures.cpp @@ -150,9 +153,7 @@ set(srcs src/rsd.cpp src/grsd.cpp src/statistical_multiscale_interest_region_extraction.cpp - src/vfh.cpp src/esf.cpp - src/3dsc.cpp src/usc.cpp src/range_image_border_extractor.cpp ) diff --git a/features/include/pcl/features/impl/feature.hpp b/features/include/pcl/features/impl/feature.hpp index f185225f..fc8c19e5 100644 --- a/features/include/pcl/features/impl/feature.hpp +++ b/features/include/pcl/features/impl/feature.hpp @@ -119,14 +119,22 @@ Feature::initCompute () // Check if a space search locator was given if (!tree_) { - if (surface_->isOrganized () && input_->isOrganized ()) + if (surface_->isOrganized () && input_->isOrganized ()) { tree_.reset (new pcl::search::OrganizedNeighbor ()); - else + if(!tree_->setInputCloud (surface_)) { // may return false if OrganizedNeighbor cannot work with the cloud, then use KdTree instead + tree_.reset (new pcl::search::KdTree (false)); + } + } else { tree_.reset (new pcl::search::KdTree (false)); + } } - if (tree_->getInputCloud () != surface_) // Make sure the tree searches the surface - tree_->setInputCloud (surface_); + if (tree_->getInputCloud () != surface_) { // Make sure the tree searches the surface + if(!tree_->setInputCloud (surface_)) { + PCL_ERROR ("[pcl::%s::compute] The given search method cannot work with the given input cloud/search surface.\n", getClassName ().c_str ()); + return (false); + } + } // Do a fast check to see if the search parameters are well defined diff --git a/features/include/pcl/features/impl/flare.hpp b/features/include/pcl/features/impl/flare.hpp index e00f242f..2bd9cb8f 100644 --- a/features/include/pcl/features/impl/flare.hpp +++ b/features/include/pcl/features/impl/flare.hpp @@ -178,8 +178,6 @@ template::max (); int best_shape_index = -1; - Eigen::Vector3f best_margin_point; - const float radius2 = tangent_radius_ * tangent_radius_; const float margin_distance2 = margin_thresh_ * margin_thresh_ * radius2; diff --git a/features/include/pcl/features/impl/integral_image2D.hpp b/features/include/pcl/features/impl/integral_image2D.hpp index a8ffd0e5..bc2ab4fd 100644 --- a/features/include/pcl/features/impl/integral_image2D.hpp +++ b/features/include/pcl/features/impl/integral_image2D.hpp @@ -194,7 +194,6 @@ IntegralImage2D::computeIntegralImages ( for (unsigned int i = 0; i < (width_ + 1); ++i) so_previous_row[i].setZero(); - SecondOrderType so_element; for (unsigned rowIdx = 0; rowIdx < height_; ++rowIdx, data += row_stride, previous_row = current_row, current_row += (width_ + 1), count_previous_row = count_current_row, count_current_row += (width_ + 1), diff --git a/features/include/pcl/features/impl/intensity_gradient.hpp b/features/include/pcl/features/impl/intensity_gradient.hpp index fcb8c85f..d9e7baf3 100644 --- a/features/include/pcl/features/impl/intensity_gradient.hpp +++ b/features/include/pcl/features/impl/intensity_gradient.hpp @@ -136,7 +136,7 @@ pcl::IntensityGradientEstimation ::computeOBB () obb_max_point_.y -= shift (1); obb_max_point_.z -= shift (2); - obb_position_ = mean_value_ + obb_rotational_matrix_ * shift; + obb_position_.noalias() = mean_value_ + obb_rotational_matrix_ * shift; } ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -366,7 +366,7 @@ pcl::MomentOfInertiaEstimation::computeCovarianceMatrix (Eigen::Matrix < current_point (1) = (*input_)[(*indices_)[i_point]].y - mean_value_ (1); current_point (2) = (*input_)[(*indices_)[i_point]].z - mean_value_ (2); - covariance_matrix += current_point * current_point.transpose (); + covariance_matrix.noalias() += current_point * current_point.transpose (); } covariance_matrix *= factor; @@ -387,7 +387,7 @@ pcl::MomentOfInertiaEstimation::computeCovarianceMatrix (PointCloudConst current_point (1) = (*cloud)[i_point].y - mean_value_ (1); current_point (2) = (*cloud)[i_point].z - mean_value_ (2); - covariance_matrix += current_point * current_point.transpose (); + covariance_matrix.noalias() += current_point * current_point.transpose (); } covariance_matrix *= factor; @@ -399,47 +399,44 @@ pcl::MomentOfInertiaEstimation::computeEigenVectors (const Eigen::Matrix Eigen::Vector3f& major_axis, Eigen::Vector3f& middle_axis, Eigen::Vector3f& minor_axis, float& major_value, float& middle_value, float& minor_value) { - Eigen::EigenSolver > eigen_solver; - eigen_solver.compute (covariance_matrix); + const Eigen::SelfAdjointEigenSolver> eigen_solver(covariance_matrix); - Eigen::EigenSolver >::EigenvectorsType eigen_vectors; - Eigen::EigenSolver >::EigenvalueType eigen_values; - eigen_vectors = eigen_solver.eigenvectors (); - eigen_values = eigen_solver.eigenvalues (); + const Eigen::SelfAdjointEigenSolver >::EigenvectorsType& eigen_vectors = eigen_solver.eigenvectors (); + const Eigen::SelfAdjointEigenSolver >::RealVectorType& eigen_values = eigen_solver.eigenvalues (); unsigned int temp = 0; unsigned int major_index = 0; unsigned int middle_index = 1; unsigned int minor_index = 2; - if (eigen_values.real () (major_index) < eigen_values.real () (middle_index)) + if (eigen_values (major_index) < eigen_values (middle_index)) { temp = major_index; major_index = middle_index; middle_index = temp; } - if (eigen_values.real () (major_index) < eigen_values.real () (minor_index)) + if (eigen_values (major_index) < eigen_values (minor_index)) { temp = major_index; major_index = minor_index; minor_index = temp; } - if (eigen_values.real () (middle_index) < eigen_values.real () (minor_index)) + if (eigen_values (middle_index) < eigen_values (minor_index)) { temp = minor_index; minor_index = middle_index; middle_index = temp; } - major_value = eigen_values.real () (major_index); - middle_value = eigen_values.real () (middle_index); - minor_value = eigen_values.real () (minor_index); + major_value = eigen_values (major_index); + middle_value = eigen_values (middle_index); + minor_value = eigen_values (minor_index); - major_axis = eigen_vectors.col (major_index).real (); - middle_axis = eigen_vectors.col (middle_index).real (); - minor_axis = eigen_vectors.col (minor_index).real (); + major_axis = eigen_vectors.col (major_index); + middle_axis = eigen_vectors.col (middle_index); + minor_axis = eigen_vectors.col (minor_index); major_axis.normalize (); middle_axis.normalize (); diff --git a/features/include/pcl/features/impl/our_cvfh.hpp b/features/include/pcl/features/impl/our_cvfh.hpp index 15fab154..cde8a32d 100644 --- a/features/include/pcl/features/impl/our_cvfh.hpp +++ b/features/include/pcl/features/impl/our_cvfh.hpp @@ -260,7 +260,7 @@ pcl::OURCVFHEstimation::sgurf (Eigen::Vector3f & c scatter /= sum_w; - Eigen::JacobiSVD svd (scatter, Eigen::ComputeFullV); + const Eigen::JacobiSVD svd (scatter, Eigen::ComputeFullV); Eigen::Vector3f evx = svd.matrixV ().col (0); Eigen::Vector3f evy = svd.matrixV ().col (1); Eigen::Vector3f evz = svd.matrixV ().col (2); diff --git a/features/include/pcl/features/impl/principal_curvatures.hpp b/features/include/pcl/features/impl/principal_curvatures.hpp index 8c0561c4..9659aae5 100644 --- a/features/include/pcl/features/impl/principal_curvatures.hpp +++ b/features/include/pcl/features/impl/principal_curvatures.hpp @@ -78,7 +78,7 @@ pcl::PrincipalCurvaturesEstimation::computePointPr for (std::size_t idx = 0; idx < indices.size(); ++idx) { const auto normal = normals[indices[idx]].getNormalVector3fMap(); - projected_normals[idx] = M * normal; + projected_normals[idx].noalias() = M * normal; xyz_centroid += projected_normals[idx]; } diff --git a/features/include/pcl/features/impl/rops_estimation.hpp b/features/include/pcl/features/impl/rops_estimation.hpp index f454f75c..e3ec24cb 100644 --- a/features/include/pcl/features/impl/rops_estimation.hpp +++ b/features/include/pcl/features/impl/rops_estimation.hpp @@ -275,9 +275,9 @@ pcl::ROPSEstimation ::computeLRF (const PointInT& point, co for (const auto &i_pt : pt) { Eigen::Vector3f vec = i_pt - feature_point; - curr_scatter_matrix += vec * (vec.transpose ()); + curr_scatter_matrix.noalias() += vec * (vec.transpose ()); for (const auto &j_pt : pt) - curr_scatter_matrix += vec * ((j_pt - feature_point).transpose ()); + curr_scatter_matrix.noalias() += vec * ((j_pt - feature_point).transpose ()); } scatter_matrices.emplace_back (coeff * curr_scatter_matrix); } @@ -343,43 +343,40 @@ template void pcl::ROPSEstimation ::computeEigenVectors (const Eigen::Matrix3f& matrix, Eigen::Vector3f& major_axis, Eigen::Vector3f& middle_axis, Eigen::Vector3f& minor_axis) const { - Eigen::EigenSolver eigen_solver; - eigen_solver.compute (matrix); + Eigen::SelfAdjointEigenSolver eigen_solver(matrix, Eigen::ComputeEigenvectors); - Eigen::EigenSolver ::EigenvectorsType eigen_vectors; - Eigen::EigenSolver ::EigenvalueType eigen_values; - eigen_vectors = eigen_solver.eigenvectors (); - eigen_values = eigen_solver.eigenvalues (); + const Eigen::SelfAdjointEigenSolver ::EigenvectorsType& eigen_vectors = eigen_solver.eigenvectors (); + const Eigen::SelfAdjointEigenSolver ::RealVectorType& eigen_values = eigen_solver.eigenvalues (); unsigned int temp = 0; unsigned int major_index = 0; unsigned int middle_index = 1; unsigned int minor_index = 2; - if (eigen_values.real () (major_index) < eigen_values.real () (middle_index)) + if (eigen_values (major_index) < eigen_values (middle_index)) { temp = major_index; major_index = middle_index; middle_index = temp; } - if (eigen_values.real () (major_index) < eigen_values.real () (minor_index)) + if (eigen_values (major_index) < eigen_values (minor_index)) { temp = major_index; major_index = minor_index; minor_index = temp; } - if (eigen_values.real () (middle_index) < eigen_values.real () (minor_index)) + if (eigen_values (middle_index) < eigen_values (minor_index)) { temp = minor_index; minor_index = middle_index; middle_index = temp; } - major_axis = eigen_vectors.col (major_index).real (); - middle_axis = eigen_vectors.col (middle_index).real (); - minor_axis = eigen_vectors.col (minor_index).real (); + major_axis = eigen_vectors.col (major_index); + middle_axis = eigen_vectors.col (middle_index); + minor_axis = eigen_vectors.col (minor_index); } ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/features/include/pcl/features/impl/shot_lrf.hpp b/features/include/pcl/features/impl/shot_lrf.hpp index 1d99772b..e1729954 100644 --- a/features/include/pcl/features/impl/shot_lrf.hpp +++ b/features/include/pcl/features/impl/shot_lrf.hpp @@ -77,7 +77,7 @@ pcl::SHOTLocalReferenceFrameEstimation::getLocalRF (const i distance = search_parameter_ - sqrt (n_sqr_distances[i_idx]); // Multiply vij * vij' - cov_m += distance * (vij.row (valid_nn_points).head<3> ().transpose () * vij.row (valid_nn_points).head<3> ()); + cov_m.noalias() += distance * (vij.row (valid_nn_points).head<3> ().transpose () * vij.row (valid_nn_points).head<3> ()); sum += distance; valid_nn_points++; diff --git a/features/include/pcl/features/impl/shot_lrf_omp.hpp b/features/include/pcl/features/impl/shot_lrf_omp.hpp index cde3a58d..99895a8b 100644 --- a/features/include/pcl/features/impl/shot_lrf_omp.hpp +++ b/features/include/pcl/features/impl/shot_lrf_omp.hpp @@ -74,7 +74,8 @@ pcl::SHOTLocalReferenceFrameEstimationOMP::computeFeature ( #pragma omp parallel for \ default(none) \ shared(output) \ - num_threads(threads_) + num_threads(threads_) \ + schedule(dynamic, 64) for (std::ptrdiff_t i = 0; i < static_cast (indices_->size ()); ++i) { // point result diff --git a/features/include/pcl/features/our_cvfh.h b/features/include/pcl/features/our_cvfh.h index 96947062..fda1ec99 100644 --- a/features/include/pcl/features/our_cvfh.h +++ b/features/include/pcl/features/our_cvfh.h @@ -114,7 +114,7 @@ namespace pcl homMatrix = transformPC.matrix (); Eigen::Matrix4f trans_copy = trans.inverse (); - trans = trans_copy * center_mat * homMatrix; + trans.noalias() = trans_copy * center_mat * homMatrix; return trans; } diff --git a/filters/CMakeLists.txt b/filters/CMakeLists.txt index 3fc7c641..2d62bd59 100644 --- a/filters/CMakeLists.txt +++ b/filters/CMakeLists.txt @@ -11,7 +11,9 @@ if(NOT build) return() endif() +# The cpp files have been ordered so that files with a long compile time appear at the top, to efficiently build in parallel. Do not reorder alphabetically! set(srcs + src/voxel_grid_covariance.cpp src/conditional_removal.cpp src/convolution.cpp src/crop_box.cpp @@ -33,7 +35,6 @@ set(srcs src/fast_bilateral.cpp src/fast_bilateral_omp.cpp src/crop_hull.cpp - src/voxel_grid_covariance.cpp src/voxel_grid_label.cpp src/frustum_culling.cpp src/covariance_sampling.cpp diff --git a/filters/include/pcl/filters/conditional_removal.h b/filters/include/pcl/filters/conditional_removal.h index d5e7b7cc..da66cd82 100644 --- a/filters/include/pcl/filters/conditional_removal.h +++ b/filters/include/pcl/filters/conditional_removal.h @@ -401,8 +401,8 @@ namespace pcl inline void transformComparison (const Eigen::Matrix4f &transform) { - tf_comp_matr_ = transform.transpose () * comp_matr_ * transform; - tf_comp_vect_ = comp_vect_.transpose () * transform; + tf_comp_matr_.noalias() = transform.transpose () * comp_matr_ * transform; + tf_comp_vect_.noalias() = comp_vect_.transpose () * transform; } /** \brief transform the coordinate system of the comparison. If you think of diff --git a/filters/include/pcl/filters/convolution_3d.h b/filters/include/pcl/filters/convolution_3d.h index 8cb21bde..ec6f0fc6 100644 --- a/filters/include/pcl/filters/convolution_3d.h +++ b/filters/include/pcl/filters/convolution_3d.h @@ -133,7 +133,7 @@ namespace pcl * \param[in] sigma */ inline void - setSigma (float sigma) { sigma_ = sigma; } + setSigma (float sigma) { sigma_ = sigma; sigma_sqr_ = sigma_ * sigma_; } /** Set the distance threshold relative to a sigma factor i.e. points such as * ||pi - q|| > sigma_coefficient^2 * sigma^2 are not considered. diff --git a/filters/include/pcl/filters/impl/approximate_voxel_grid.hpp b/filters/include/pcl/filters/impl/approximate_voxel_grid.hpp index eac25a54..ca3c7d95 100644 --- a/filters/include/pcl/filters/impl/approximate_voxel_grid.hpp +++ b/filters/include/pcl/filters/impl/approximate_voxel_grid.hpp @@ -39,6 +39,7 @@ #define PCL_FILTERS_IMPL_FAST_VOXEL_GRID_H_ #include +#include #include #include // for size @@ -91,6 +92,8 @@ pcl::ApproximateVoxelGrid::applyFilter (PointCloud &output) std::size_t op = 0; // output pointer for (const auto& point: *input_) { + if(!pcl::isXYZFinite(point)) + continue; int ix = static_cast (std::floor (point.x * inverse_leaf_size_[0])); int iy = static_cast (std::floor (point.y * inverse_leaf_size_[1])); int iz = static_cast (std::floor (point.z * inverse_leaf_size_[2])); @@ -130,7 +133,7 @@ pcl::ApproximateVoxelGrid::applyFilter (PointCloud &output) output.resize (op); output.width = output.size (); output.height = 1; // downsampling breaks the organized structure - output.is_dense = false; // we filter out invalid points + output.is_dense = true; // we filter out invalid points } #define PCL_INSTANTIATE_ApproximateVoxelGrid(T) template class PCL_EXPORTS pcl::ApproximateVoxelGrid; diff --git a/filters/include/pcl/filters/impl/covariance_sampling.hpp b/filters/include/pcl/filters/impl/covariance_sampling.hpp index a3885cf6..eef95711 100644 --- a/filters/include/pcl/filters/impl/covariance_sampling.hpp +++ b/filters/include/pcl/filters/impl/covariance_sampling.hpp @@ -122,7 +122,7 @@ pcl::CovarianceSampling::computeCovarianceMatrix (Eigen::Matrix } // Compute the covariance matrix C and its 6 eigenvectors (initially complex, move them to a double matrix) - covariance_matrix = f_mat * f_mat.transpose (); + covariance_matrix.noalias() = f_mat * f_mat.transpose (); return true; } diff --git a/filters/include/pcl/filters/impl/farthest_point_sampling.hpp b/filters/include/pcl/filters/impl/farthest_point_sampling.hpp index 78da79c3..afdf41aa 100644 --- a/filters/include/pcl/filters/impl/farthest_point_sampling.hpp +++ b/filters/include/pcl/filters/impl/farthest_point_sampling.hpp @@ -20,7 +20,7 @@ template void pcl::FarthestPointSampling::applyFilter (Indices &indices) { - const std::size_t size = input_->size(); + const std::size_t size = indices_->size(); //if requested number of point is equal to the point cloud size, copy original cloud if (sample_size_ == size) { @@ -41,22 +41,25 @@ pcl::FarthestPointSampling::applyFilter (Indices &indices) std::mt19937 random_gen(seed_); std::uniform_int_distribution dis(0, size -1); + //lambda to map filter indices back to pointcloud indices for increased readability + auto toCloudIndex = [this](const auto idx){return (*indices_)[idx];}; + //pick the first point at random index_t max_index = dis(random_gen); distances_to_selected_points[max_index] = -1.0; - indices.push_back(max_index); + indices.push_back(toCloudIndex(max_index)); for (std::size_t j = 1; j < sample_size_; ++j) { index_t next_max_index = 0; - const PointT& max_index_point = (*input_)[max_index]; + const PointT& max_index_point = (*input_)[toCloudIndex(max_index)]; //recompute distances for (std::size_t i = 0; i < size; ++i) { if (distances_to_selected_points[i] == -1.0) continue; - distances_to_selected_points[i] = std::min(distances_to_selected_points[i], geometry::distance((*input_)[i], max_index_point)); + distances_to_selected_points[i] = std::min(distances_to_selected_points[i], geometry::distance((*input_)[toCloudIndex(i)], max_index_point)); if (distances_to_selected_points[i] > distances_to_selected_points[next_max_index]) next_max_index = i; } @@ -66,7 +69,7 @@ pcl::FarthestPointSampling::applyFilter (Indices &indices) //elements are guaranteed to not be selected max_index = next_max_index; distances_to_selected_points[max_index] = -1.0; - indices.push_back(max_index); + indices.push_back(toCloudIndex(max_index)); //set distance to -1 to ignore during max element search } @@ -75,7 +78,7 @@ pcl::FarthestPointSampling::applyFilter (Indices &indices) for (std::size_t k = 0; k < distances_to_selected_points.size(); ++k) { if (distances_to_selected_points[k] != -1.0) - (*removed_indices_).push_back(k); + (*removed_indices_).push_back(toCloudIndex(k)); } } } diff --git a/filters/include/pcl/filters/impl/shadowpoints.hpp b/filters/include/pcl/filters/impl/shadowpoints.hpp index f2246ee6..dfcbb330 100644 --- a/filters/include/pcl/filters/impl/shadowpoints.hpp +++ b/filters/include/pcl/filters/impl/shadowpoints.hpp @@ -69,6 +69,8 @@ pcl::ShadowPoints::applyFilter (PointCloud &output) { PointT &pt_new = output[cp++] = pt; pt_new.x = pt_new.y = pt_new.z = user_filter_value_; + if(!std::isfinite(user_filter_value_)) + output.is_dense = false; } } diff --git a/filters/include/pcl/filters/impl/voxel_grid_covariance.hpp b/filters/include/pcl/filters/impl/voxel_grid_covariance.hpp index 1c60d354..fdd02c98 100644 --- a/filters/include/pcl/filters/impl/voxel_grid_covariance.hpp +++ b/filters/include/pcl/filters/impl/voxel_grid_covariance.hpp @@ -175,7 +175,7 @@ pcl::VoxelGridCovariance::applyFilter (PointCloud &output) // Accumulate point sum for centroid calculation leaf.mean_ += pt3d; // Accumulate x*xT for single pass covariance calculation - leaf.cov_ += pt3d * pt3d.transpose (); + leaf.cov_.noalias() += pt3d * pt3d.transpose (); // Do we need to process all the fields? if (!downsample_all_data_) @@ -231,7 +231,7 @@ pcl::VoxelGridCovariance::applyFilter (PointCloud &output) // Accumulate point sum for centroid calculation leaf.mean_ += pt3d; // Accumulate x*xT for single pass covariance calculation - leaf.cov_ += pt3d * pt3d.transpose (); + leaf.cov_.noalias() += pt3d * pt3d.transpose (); // Do we need to process all the fields? if (!downsample_all_data_) @@ -349,7 +349,7 @@ pcl::VoxelGridCovariance::applyFilter (PointCloud &output) eigen_val (1, 1) = min_covar_eigvalue; } - leaf.cov_ = leaf.evecs_ * eigen_val * leaf.evecs_.inverse (); + leaf.cov_.noalias() = leaf.evecs_ * eigen_val * leaf.evecs_.inverse (); } leaf.evals_ = eigen_val.diagonal (); @@ -475,7 +475,7 @@ pcl::VoxelGridCovariance::getDisplayCloud (pcl::PointCloud& ce for (int i = 0; i < pnt_per_cell; i++) { rand_point = Eigen::Vector3d (var_nor (), var_nor (), var_nor ()); - dist_point = cell_mean + cholesky_decomp * rand_point; + dist_point.noalias() = cell_mean + cholesky_decomp * rand_point; cell_cloud.push_back (PointXYZ (static_cast (dist_point (0)), static_cast (dist_point (1)), static_cast (dist_point (2)))); } } diff --git a/filters/src/convolution.cpp b/filters/src/convolution.cpp index 41ffd02b..fbdc0b44 100644 --- a/filters/src/convolution.cpp +++ b/filters/src/convolution.cpp @@ -189,5 +189,20 @@ Convolution::convolveOneColDense(int i, int j) result.b = static_cast(b); return (result); } + +#ifdef _MSC_VER +// Seems to be necessary with MSVC, but not necessary with other compilers (even produces warning with PCL_SYMBOL_VISIBILITY_HIDDEN and gcc) +#ifndef PCL_NO_PRECOMPILE +#include +#include + +PCL_INSTANTIATE_PRODUCT( + Convolution, ((pcl::RGB))((pcl::RGB))) + +PCL_INSTANTIATE_PRODUCT( + Convolution, ((pcl::PointXYZRGB))((pcl::PointXYZRGB))) +#endif // PCL_NO_PRECOMPILE +#endif // _MSC_VER + } // namespace filters } // namespace pcl diff --git a/gpu/containers/src/initialization.cpp b/gpu/containers/src/initialization.cpp index dbd4cadf..6038d6ae 100644 --- a/gpu/containers/src/initialization.cpp +++ b/gpu/containers/src/initialization.cpp @@ -229,8 +229,10 @@ pcl::gpu::printCudaDeviceInfo(int device) prop.multiProcessorCount, sm_cores, sm_cores * prop.multiProcessorCount); + int clockRate; + cudaSafeCall(cudaDeviceGetAttribute(&clockRate, cudaDevAttrClockRate, dev)); printf(" GPU Clock Speed: %.2f GHz\n", - prop.clockRate * 1e-6f); + clockRate * 1e-6f); // This is not available in the CUDA Runtime API, so we make the necessary calls the // driver API to support this for output @@ -285,10 +287,13 @@ pcl::gpu::printCudaDeviceInfo(int device) printf( " Concurrent copy and execution: %s with %d copy engine(s)\n", - (prop.deviceOverlap ? "Yes" : "No"), + (prop.asyncEngineCount ? "Yes" : "No"), prop.asyncEngineCount); + int kernelExecTimeoutEnabled; + cudaSafeCall(cudaDeviceGetAttribute( + &kernelExecTimeoutEnabled, cudaDevAttrKernelExecTimeout, dev)); printf(" Run time limit on kernels: %s\n", - prop.kernelExecTimeoutEnabled ? "Yes" : "No"); + kernelExecTimeoutEnabled ? "Yes" : "No"); printf(" Integrated GPU sharing Host Memory: %s\n", prop.integrated ? "Yes" : "No"); printf(" Support host page-locked memory mapping: %s\n", @@ -307,8 +312,10 @@ pcl::gpu::printCudaDeviceInfo(int device) printf(" Device PCI Bus ID / PCI location ID: %d / %d\n", prop.pciBusID, prop.pciDeviceID); + int propComputeMode; + cudaSafeCall(cudaDeviceGetAttribute(&propComputeMode, cudaDevAttrComputeMode, dev)); printf(" Compute Mode:\n"); - printf(" %s \n", computeMode[prop.computeMode]); + printf(" %s \n", computeMode[propComputeMode]); } printf("\n"); diff --git a/gpu/containers/src/repacks.cu b/gpu/containers/src/repacks.cu index e99956a7..e36b69a7 100644 --- a/gpu/containers/src/repacks.cu +++ b/gpu/containers/src/repacks.cu @@ -3,97 +3,94 @@ #include -namespace pcl +namespace pcl { +namespace device { +struct Info { + enum { SIZE = 4 }; + int data[SIZE]; +}; + +template +struct Point { + int data[n]; +}; + +template +__global__ void +deviceCopyFields4B(const Info info, const int size, const void* input, void* output) { - namespace device - { - struct Info - { - enum { SIZE = 4 }; - int data[SIZE]; - }; - - template - struct Point - { - int data[n]; - }; - - template - __global__ void deviceCopyFields4B(const Info info, const int size, const void* input, void* output) - { - int idx = blockIdx.x * blockDim.x + threadIdx.x; - - if (idx < size) - { - Point point_in = reinterpret_cast* >( input)[idx]; - Point point_out = reinterpret_cast< Point* >(output)[idx]; + int idx = blockIdx.x * blockDim.x + threadIdx.x; - for(int i = 0; i < Info::SIZE; ++i) - { - int byte; - int code = info.data[i]; + if (idx < size) { + Point point_in = reinterpret_cast*>(input)[idx]; + Point point_out = reinterpret_cast*>(output)[idx]; - byte = ((code >> 0) & 0xFF); + for (int i = 0; i < Info::SIZE; ++i) { + int byte; + int code = info.data[i]; - if (byte == 0xFF) - break; - else - point_out.data[byte >> 4] = point_in.data[byte & 0xF]; + byte = ((code >> 0) & 0xFF); - byte = ((code >> 8) & 0xFF); + if (byte == 0xFF) + break; + else + point_out.data[byte >> 4] = point_in.data[byte & 0xF]; - if (byte == 0xFF) - break; - else - point_out.data[byte >> 4] = point_in.data[byte & 0xF]; + byte = ((code >> 8) & 0xFF); - byte = ((code >> 16) & 0xFF); + if (byte == 0xFF) + break; + else + point_out.data[byte >> 4] = point_in.data[byte & 0xF]; - if (byte == 0xFF) - break; - else - point_out.data[byte >> 4] = point_in.data[byte & 0xF]; + byte = ((code >> 16) & 0xFF); - byte = ((code >> 24) & 0xFF); + if (byte == 0xFF) + break; + else + point_out.data[byte >> 4] = point_in.data[byte & 0xF]; - if (byte == 0xFF) - break; - else - point_out.data[byte >> 4] = point_in.data[byte & 0xF]; - } + byte = ((code >> 24) & 0xFF); - reinterpret_cast< Point* >(output)[idx] = point_out; - } - }; + if (byte == 0xFF) + break; + else + point_out.data[byte >> 4] = point_in.data[byte & 0xF]; + } - template - void cf(int info[4], int size, const void* input, void* output) - { - Info i; - std::copy(info, info + 4, i.data); + reinterpret_cast*>(output)[idx] = point_out; + } +}; - dim3 block(256); - dim3 grid(divUp(size, block.x)); +template +void +cf(int info[4], int size, const void* input, void* output) +{ + Info i; + std::copy(info, info + 4, i.data); - deviceCopyFields4B<<>>(i, size, input, output); - cudaSafeCall ( cudaGetLastError () ); - cudaSafeCall (cudaDeviceSynchronize ()); - } + dim3 block(256); + dim3 grid(divUp(size, block.x)); - using copy_fields_t = void (*)(int info[4], int size, const void* input, void* output); - } + deviceCopyFields4B<<>>(i, size, input, output); + cudaSafeCall(cudaGetLastError()); + cudaSafeCall(cudaDeviceSynchronize()); } -namespace pcl -{ - namespace gpu - { - using namespace pcl::device; +using copy_fields_t = void (*)(int info[4], int size, const void* input, void* output); +} // namespace device +} // namespace pcl - PCL_EXPORTS void copyFieldsImpl(int in_size, int out_size, int rules[4], int size, const void* input, void* output) - { - pcl::device::copy_fields_t funcs[16][16] = +namespace pcl { +namespace gpu { +using namespace pcl::device; + +PCL_EXPORTS void +copyFieldsImpl( + int in_size, int out_size, int rules[4], int size, const void* input, void* output) +{ + // clang-format off + pcl::device::copy_fields_t funcs[16][16] = { { /**/ cf<1,1>, cf<1, 2>, cf<1, 3>, cf<1, 4>, /**/ cf<1, 5>, cf<1, 6>, cf<1, 7>, cf<1, 8>, /**/ cf<1, 9>, cf<1,10>, cf<1, 11>, cf<1, 12>, /**/ cf<1, 13>, cf<1, 14>, cf<1, 15>, cf<1,16> }, { /**/ cf<2,1>, cf<2, 2>, cf<2, 3>, cf<2, 4>, /**/ cf<2, 5>, cf<2, 6>, cf<2, 7>, cf<2, 8>, /**/ cf<2, 9>, cf<1,10>, cf<2, 11>, cf<2, 12>, /**/ cf<2, 13>, cf<2, 14>, cf<2, 15>, cf<2,16> }, @@ -112,9 +109,8 @@ namespace pcl { /**/ cf<15,1>, cf<15,2>, cf<15,3>, cf<15,4>, /**/ cf<15,5>, cf<15,6>, cf<15,7>, cf<15,8>, /**/ cf<15,9>, cf<1,10>, cf<15,11>, cf<15,12>, /**/ cf<15,13>, cf<15,14>, cf<15,15>, cf<15,16> }, { /**/ cf<16,1>, cf<16,2>, cf<16,3>, cf<16,4>, /**/ cf<16,5>, cf<16,6>, cf<16,7>, cf<16,8>, /**/ cf<16,9>, cf<1,10>, cf<16,11>, cf<16,12>, /**/ cf<16,13>, cf<16,14>, cf<16,15>, cf<16,16> } }; - - funcs[in_size-1][out_size-1](rules, size, input, output); - } - } + // clang-format on + funcs[in_size - 1][out_size - 1](rules, size, input, output); } - +} // namespace gpu +} // namespace pcl diff --git a/gpu/features/src/centroid.cu b/gpu/features/src/centroid.cu index 8ba0f80e..1dbd029c 100644 --- a/gpu/features/src/centroid.cu +++ b/gpu/features/src/centroid.cu @@ -89,7 +89,7 @@ void pcl::device::compute3DCentroid(const DeviceArray& cloud, float3& ce thrust::device_ptr src_beg((PointT*)cloud.ptr()); thrust::device_ptr src_end = src_beg + cloud.size(); - centroid = transform_reduce(src_beg, src_beg, PointT2float3(), make_float3(0.f, 0.f, 0.f), PlusFloat3()); + centroid = thrust::transform_reduce(src_beg, src_beg, PointT2float3(), make_float3(0.f, 0.f, 0.f), PlusFloat3()); centroid *= 1.f/cloud.size(); } @@ -105,7 +105,7 @@ void pcl::device::compute3DCentroid(const DeviceArray& cloud, const Indi thrust::device_ptr map_end = map_beg + indices.size(); - centroid = transform_reduce(make_permutation_iterator(src_beg, map_beg), + centroid = thrust::transform_reduce(make_permutation_iterator(src_beg, map_beg), make_permutation_iterator(src_beg, map_end), PointT2float3(), make_float3(0.f, 0.f, 0.f), PlusFloat3()); @@ -126,7 +126,7 @@ float3 pcl::device::getMaxDistance(const DeviceArray& cloud, const float thrust::maximum> op; thrust::tuple res = - transform_reduce( + thrust::transform_reduce( make_zip_iterator(make_tuple( src_beg, cf )), make_zip_iterator(make_tuple( src_beg, ce )), TupleDistCvt(pivot), init, op); @@ -153,7 +153,7 @@ float3 pcl::device::getMaxDistance(const DeviceArray& cloud, const Indic thrust::tuple init(0.f, 0); thrust::maximum> op; - thrust::tuple res = transform_reduce( + thrust::tuple res = thrust::transform_reduce( make_zip_iterator(make_tuple( make_permutation_iterator(src_beg, map_beg), cf )), make_zip_iterator(make_tuple( make_permutation_iterator(src_beg, map_end), ce )), TupleDistCvt(pivot), init, op); diff --git a/gpu/features/src/fpfh.cu b/gpu/features/src/fpfh.cu index 211da113..7fdb3c33 100644 --- a/gpu/features/src/fpfh.cu +++ b/gpu/features/src/fpfh.cu @@ -39,12 +39,8 @@ #include "pcl/gpu/utils/safe_call.hpp" #include "pcl/gpu/utils/device/warp.hpp" #include "pcl/gpu/utils/device/functional.hpp" -#include "pcl/gpu/utils/device/funcattrib.hpp" -#include "pcl/gpu/utils/timers_cuda.hpp" #include "pcl/gpu/features/device/pair_features.hpp" -#include - using namespace pcl::gpu; using namespace pcl::device; @@ -124,7 +120,7 @@ namespace pcl float hist_incr = 100.f / (float)(size - 1); // or 100/(size - 1) ??? - //now [inds, inds + size) contains indices of neighb points for idx-th point in cloud + //now [inds, inds + size) contains indices of neighboring points for idx-th point in cloud //this list also contains idx itseelf. for(int i = lane; i < size; i += Warp::STRIDE) diff --git a/gpu/utils/include/pcl/gpu/utils/device/functional.hpp b/gpu/utils/include/pcl/gpu/utils/device/functional.hpp index 743c4cf9..30439975 100644 --- a/gpu/utils/include/pcl/gpu/utils/device/functional.hpp +++ b/gpu/utils/include/pcl/gpu/utils/device/functional.hpp @@ -39,14 +39,12 @@ #define PCL_DEVICE_FUNCTIONAL_HPP_ #include +#include namespace pcl { namespace device { - // Function Objects - - using thrust::binary_function; // Arithmetic Operations @@ -87,7 +85,11 @@ namespace pcl // Generalized Identity Operations - using thrust::identity; + #if CUDA_VERSION >= 13000 + using cuda::std::identity; + #else + using thrust::identity; + #endif using thrust::project1st; using thrust::project2nd; diff --git a/io/include/pcl/compression/point_coding.h b/io/include/pcl/compression/point_coding.h index b365c189..0587329e 100644 --- a/io/include/pcl/compression/point_coding.h +++ b/io/include/pcl/compression/point_coding.h @@ -169,9 +169,9 @@ class PointCoding PointT& point = (*outputCloud_arg)[beginIdx_arg + i]; // decode point position - point.x = static_cast (referencePoint_arg[0] + diffX * pointCompressionResolution_); - point.y = static_cast (referencePoint_arg[1] + diffY * pointCompressionResolution_); - point.z = static_cast (referencePoint_arg[2] + diffZ * pointCompressionResolution_); + point.x = static_cast (referencePoint_arg[0] + (diffX+0.5) * pointCompressionResolution_); + point.y = static_cast (referencePoint_arg[1] + (diffY+0.5) * pointCompressionResolution_); + point.z = static_cast (referencePoint_arg[2] + (diffZ+0.5) * pointCompressionResolution_); } } diff --git a/io/include/pcl/io/ifs_io.h b/io/include/pcl/io/ifs_io.h index 6b4b2016..d898d85f 100644 --- a/io/include/pcl/io/ifs_io.h +++ b/io/include/pcl/io/ifs_io.h @@ -172,7 +172,7 @@ namespace pcl const std::string &cloud_name = "cloud") { pcl::PCLPointCloud2 blob; - pcl::toPCLPointCloud2 (cloud, blob); + pcl::toPCLPointCloud2 (cloud, blob, false); // no padding return (write (file_name, blob, cloud_name)); } }; diff --git a/io/include/pcl/io/impl/vtk_lib_io.hpp b/io/include/pcl/io/impl/vtk_lib_io.hpp index 477ed686..38cad081 100644 --- a/io/include/pcl/io/impl/vtk_lib_io.hpp +++ b/io/include/pcl/io/impl/vtk_lib_io.hpp @@ -122,7 +122,7 @@ pcl::io::vtkPolyDataToPointCloud (vtkPolyData* const polydata, pcl::PointCloud

GetTupleValue (i, normal); pcl::setFieldValue (cloud[i], normal_x_idx, normal[0]); pcl::setFieldValue (cloud[i], normal_y_idx, normal[1]); diff --git a/io/src/dinast_grabber.cpp b/io/src/dinast_grabber.cpp index 1cd33ba2..fec47a48 100644 --- a/io/src/dinast_grabber.cpp +++ b/io/src/dinast_grabber.cpp @@ -353,7 +353,7 @@ pcl::DinastGrabber::USBRxControlData (const unsigned char req_code, int length) { // The direction of the transfer is inferred from the requesttype field of the setup packet. - unsigned char requesttype = (LIBUSB_RECIPIENT_DEVICE | LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_ENDPOINT_IN); + const unsigned char requesttype = (static_cast(LIBUSB_RECIPIENT_DEVICE) | static_cast(LIBUSB_REQUEST_TYPE_VENDOR) | static_cast(LIBUSB_ENDPOINT_IN)); // The value field for the setup packet std::uint16_t value = 0x02; // The index field for the setup packet @@ -377,7 +377,7 @@ pcl::DinastGrabber::USBTxControlData (const unsigned char req_code, int length) { // The direction of the transfer is inferred from the requesttype field of the setup packet. - unsigned char requesttype = (LIBUSB_RECIPIENT_DEVICE | LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_ENDPOINT_OUT); + const unsigned char requesttype = (static_cast(LIBUSB_RECIPIENT_DEVICE) | static_cast(LIBUSB_REQUEST_TYPE_VENDOR) | static_cast(LIBUSB_ENDPOINT_OUT)); // The value field for the setup packet std::uint16_t value = 0x01; // The index field for the setup packet diff --git a/keypoints/include/pcl/keypoints/impl/iss_3d.hpp b/keypoints/include/pcl/keypoints/impl/iss_3d.hpp index 6c298c7b..a14a1bf9 100644 --- a/keypoints/include/pcl/keypoints/impl/iss_3d.hpp +++ b/keypoints/include/pcl/keypoints/impl/iss_3d.hpp @@ -373,7 +373,7 @@ pcl::ISSKeypoint3D::detectKeypoints (PointCloudOut Eigen::Matrix3d cov_m = Eigen::Matrix3d::Zero (); getScatterMatrix (static_cast (index), cov_m); - Eigen::SelfAdjointEigenSolver solver (cov_m); + const Eigen::SelfAdjointEigenSolver solver (cov_m, Eigen::EigenvaluesOnly); const double& e1c = solver.eigenvalues ()[2]; const double& e2c = solver.eigenvalues ()[1]; diff --git a/keypoints/include/pcl/keypoints/impl/smoothed_surfaces_keypoint.hpp b/keypoints/include/pcl/keypoints/impl/smoothed_surfaces_keypoint.hpp index 4f612bcb..07604d7a 100644 --- a/keypoints/include/pcl/keypoints/impl/smoothed_surfaces_keypoint.hpp +++ b/keypoints/include/pcl/keypoints/impl/smoothed_surfaces_keypoint.hpp @@ -230,7 +230,7 @@ pcl::SmoothedSurfacesKeypoint::initCompute () cloud_normals_.push_back (normals_); cloud_trees_.push_back (tree_); // Sort the clouds by their scales - sort (scales_.begin (), scales_.end (), compareScalesFunction); + std::sort (scales_.begin (), scales_.end (), compareScalesFunction); // Find the index of the input after sorting for (std::size_t i = 0; i < scales_.size (); ++i) diff --git a/ml/src/svm.cpp b/ml/src/svm.cpp index 59e8dfcf..d885b222 100644 --- a/ml/src/svm.cpp +++ b/ml/src/svm.cpp @@ -124,7 +124,7 @@ info(const char* fmt, ...) char buf[BUFSIZ]; va_list ap; va_start(ap, fmt); - vsprintf(buf, fmt, ap); + vsnprintf(buf, BUFSIZ, fmt, ap); va_end(ap); (*svm_print_string)(buf); } diff --git a/octree/include/pcl/octree/impl/octree_pointcloud.hpp b/octree/include/pcl/octree/impl/octree_pointcloud.hpp index fcabeca1..7bf840d5 100644 --- a/octree/include/pcl/octree/impl/octree_pointcloud.hpp +++ b/octree/include/pcl/octree/impl/octree_pointcloud.hpp @@ -517,9 +517,9 @@ pcl::octree::OctreePointCloud // octree not empty - we add another tree level and thus increase its size by a // factor of 2*2*2 - child_idx = static_cast(((bLowerBoundViolationX) << 2) | - ((bLowerBoundViolationY) << 1) | - ((bLowerBoundViolationZ))); + child_idx = static_cast((bLowerBoundViolationX ? 4 : 0) | + (bLowerBoundViolationY ? 2 : 0) | + (bLowerBoundViolationZ ? 1 : 0)); BranchNode* newRootBranch; diff --git a/octree/include/pcl/octree/impl/octree_search.hpp b/octree/include/pcl/octree/impl/octree_search.hpp index 31a84656..144609ba 100644 --- a/octree/include/pcl/octree/impl/octree_search.hpp +++ b/octree/include/pcl/octree/impl/octree_search.hpp @@ -398,13 +398,9 @@ OctreePointCloudSearch:: else { // we reached leaf node level const auto* child_leaf = static_cast(child_node); - Indices decoded_point_vector; - - // decode leaf node into decoded_point_vector - (*child_leaf)->getPointIndices(decoded_point_vector); - // Linearly iterate over all decoded (unsorted) points - for (const auto& index : decoded_point_vector) { + // Linearly iterate over all points in the leaf + for (const auto& index : (*child_leaf)->getPointIndicesVector()) { const PointT& candidate_point = this->getPointByIndex(index); // calculate point distance to search point diff --git a/octree/include/pcl/octree/octree_container.h b/octree/include/pcl/octree/octree_container.h index cd549cb6..a43882e7 100644 --- a/octree/include/pcl/octree/octree_container.h +++ b/octree/include/pcl/octree/octree_container.h @@ -324,6 +324,16 @@ public: return leafDataTVector_; } + /** \brief Retrieve const reference to point indices vector. This container stores a + * vector of point indices. + * \return const reference to vector of point indices to be stored within data vector + */ + const pcl::Indices& + getPointIndicesVector() const + { + return leafDataTVector_; + } + /** \brief Get size of container (number of indices) * \return number of point indices in container. */ diff --git a/outofcore/CMakeLists.txt b/outofcore/CMakeLists.txt index 416669b8..2d613c1e 100644 --- a/outofcore/CMakeLists.txt +++ b/outofcore/CMakeLists.txt @@ -1,6 +1,10 @@ set(SUBSYS_NAME outofcore) set(SUBSYS_DESC "Point cloud outofcore library") +if(BUILD_visualization) set(SUBSYS_DEPS common io filters octree visualization) +else() +set(SUBSYS_DEPS common io filters octree) +endif() if(NOT TARGET Boost::filesystem) set(DEFAULT FALSE) @@ -70,9 +74,13 @@ endif() set(LIB_NAME "pcl_${SUBSYS_NAME}") -PCL_ADD_LIBRARY(${LIB_NAME} COMPONENT ${SUBSYS_NAME} SOURCES ${srcs} ${incs} ${impl_incs} ${visualization_incs}) -#PCL_ADD_SSE_FLAGS("${LIB_NAME}") -target_link_libraries("${LIB_NAME}" pcl_common pcl_visualization ${Boost_SYSTEM_LIBRARY}) +if(BUILD_visualization) + PCL_ADD_LIBRARY(${LIB_NAME} COMPONENT ${SUBSYS_NAME} SOURCES ${srcs} ${incs} ${impl_incs} ${visualization_incs}) + target_link_libraries("${LIB_NAME}" pcl_common pcl_visualization Boost::system Boost::filesystem) +else() + PCL_ADD_LIBRARY(${LIB_NAME} COMPONENT ${SUBSYS_NAME} SOURCES ${srcs} ${incs} ${impl_incs}) + target_link_libraries("${LIB_NAME}" pcl_common Boost::system Boost::filesystem) +endif() if(HAVE_CJSON) target_link_libraries("${LIB_NAME}" ${CJSON_LIBRARIES}) endif() @@ -81,7 +89,9 @@ PCL_MAKE_PKGCONFIG(${LIB_NAME} COMPONENT ${SUBSYS_NAME} DESC ${SUBSYS_DESC} PCL_ # Install include files PCL_ADD_INCLUDES("${SUBSYS_NAME}" "${SUBSYS_NAME}" ${incs}) PCL_ADD_INCLUDES("${SUBSYS_NAME}" "${SUBSYS_NAME}/impl" ${impl_incs}) -PCL_ADD_INCLUDES("${SUBSYS_NAME}" "${SUBSYS_NAME}/visualization" ${visualization_incs}) +if(BUILD_visualization) + PCL_ADD_INCLUDES("${SUBSYS_NAME}" "${SUBSYS_NAME}/visualization" ${visualization_incs}) +endif() if(BUILD_tools) add_subdirectory(tools) diff --git a/outofcore/include/pcl/outofcore/impl/octree_base_node.hpp b/outofcore/include/pcl/outofcore/impl/octree_base_node.hpp index b86c7d79..67260e10 100644 --- a/outofcore/include/pcl/outofcore/impl/octree_base_node.hpp +++ b/outofcore/include/pcl/outofcore/impl/octree_base_node.hpp @@ -51,7 +51,9 @@ #include #include // pcl::utils::ignore +#ifdef PCL_VISUALIZATION_AVAILABLE #include +#endif #include #include #include @@ -1199,7 +1201,7 @@ namespace pcl } //////////////////////////////////////////////////////////////////////////////// - +#ifdef PCL_VISUALIZATION_AVAILABLE template void OutofcoreOctreeBaseNode::queryFrustum (const double planes[24], const Eigen::Vector3d &eye, const Eigen::Matrix4d &view_projection_matrix, std::list& file_names, const std::uint32_t query_depth, const bool skip_vfc_check) { @@ -1310,6 +1312,7 @@ namespace pcl } } } +#endif //////////////////////////////////////////////////////////////////////////////// template void diff --git a/outofcore/include/pcl/outofcore/octree_base_node.h b/outofcore/include/pcl/outofcore/octree_base_node.h index dba76d4f..b6cffe19 100644 --- a/outofcore/include/pcl/outofcore/octree_base_node.h +++ b/outofcore/include/pcl/outofcore/octree_base_node.h @@ -161,8 +161,15 @@ namespace pcl void queryFrustum (const double planes[24], std::list& file_names, const std::uint32_t query_depth, const bool skip_vfc_check = false); + /** \warning This function is only available if the visualization module is available and the preprocessor symbol `PCL_VISUALIZATION_AVAILABLE` is defined. + */ +#ifdef PCL_VISUALIZATION_AVAILABLE void queryFrustum (const double planes[24], const Eigen::Vector3d &eye, const Eigen::Matrix4d &view_projection_matrix, std::list& file_names, const std::uint32_t query_depth, const bool skip_vfc_check = false); +#else + void + queryFrustum (const double planes[24], const Eigen::Vector3d &eye, const Eigen::Matrix4d &view_projection_matrix, std::list& file_names, const std::uint32_t query_depth, const bool skip_vfc_check = false) = delete; +#endif //point extraction /** \brief Recursively add points that fall into the queried bounding box up to the \b query_depth diff --git a/outofcore/src/visualization/viewport.cpp b/outofcore/src/visualization/viewport.cpp index 0620f424..96591b5d 100644 --- a/outofcore/src/visualization/viewport.cpp +++ b/outofcore/src/visualization/viewport.cpp @@ -44,7 +44,7 @@ Viewport::Viewport (vtkSmartPointer window, double xmin/*=0.0*/ camera_hud_actor_->GetTextProperty ()->SetColor (0.8, 0.8, 0.8); camera_hud_actor_->GetTextProperty ()->SetJustificationToCentered (); camera_hud_actor_->SetPosition ((viewport_xmax - viewport_xmin) / 2, 10); - renderer_->AddActor2D (camera_hud_actor_); + renderer_->AddViewProp (camera_hud_actor_); // HUD - FPS fps_hud_actor_ = vtkSmartPointer::New (); @@ -53,7 +53,7 @@ Viewport::Viewport (vtkSmartPointer window, double xmin/*=0.0*/ fps_hud_actor_->GetTextProperty ()->SetJustificationToRight (); fps_hud_actor_->SetInput ("fps"); fps_hud_actor_->SetPosition ((viewport_xmax - viewport_xmin) - 10, 10); - renderer_->AddActor2D (fps_hud_actor_); + renderer_->AddViewProp (fps_hud_actor_); // HUD - Points Loaded points_hud_actor_ = vtkSmartPointer::New (); @@ -62,7 +62,7 @@ Viewport::Viewport (vtkSmartPointer window, double xmin/*=0.0*/ points_hud_actor_->GetTextProperty ()->SetJustificationToRight (); points_hud_actor_->SetInput ("points/mb"); points_hud_actor_->SetPosition ((viewport_xmax - viewport_xmin) - 10, viewport_ymax - 20); - renderer_->AddActor2D (points_hud_actor_); + renderer_->AddViewProp (points_hud_actor_); // Callback - Viewport Modified - Window Resize viewport_modified_callback_ = vtkSmartPointer::New (); diff --git a/pcl_config.h.in b/pcl_config.h.in index 5b07e0d7..2e93d63d 100644 --- a/pcl_config.h.in +++ b/pcl_config.h.in @@ -49,6 +49,10 @@ #cmakedefine HAVE_DAVIDSDK 1 +#ifndef PCL_HAS_NANOFLANN +#cmakedefine PCL_HAS_NANOFLANN 1 +#endif + // SSE macros #cmakedefine HAVE_POSIX_MEMALIGN #cmakedefine HAVE_MM_MALLOC @@ -100,3 +104,4 @@ #cmakedefine HAVE_QVTK 1 +#cmakedefine PCL_VISUALIZATION_AVAILABLE diff --git a/people/include/pcl/people/impl/ground_based_people_detection_app.hpp b/people/include/pcl/people/impl/ground_based_people_detection_app.hpp index 920c8430..3fa49629 100644 --- a/people/include/pcl/people/impl/ground_based_people_detection_app.hpp +++ b/people/include/pcl/people/impl/ground_based_people_detection_app.hpp @@ -274,7 +274,7 @@ pcl::people::GroundBasedPeopleDetectionApp::applyTransformationGround () { Eigen::Transform transform; transform = transformation_; - ground_coeffs_transformed_ = transform.matrix() * ground_coeffs_; + ground_coeffs_transformed_.noalias() = transform.matrix() * ground_coeffs_; } else { @@ -287,7 +287,7 @@ pcl::people::GroundBasedPeopleDetectionApp::applyTransformationIntrinsic { if (transformation_set_ && intrinsics_matrix_set_) { - intrinsics_matrix_transformed_ = intrinsics_matrix_ * transformation_.transpose(); + intrinsics_matrix_transformed_.noalias() = intrinsics_matrix_ * transformation_.transpose(); } else { diff --git a/recognition/CMakeLists.txt b/recognition/CMakeLists.txt index db1de1bf..0e1e7c01 100644 --- a/recognition/CMakeLists.txt +++ b/recognition/CMakeLists.txt @@ -99,7 +99,10 @@ set(cg_impl_incs "include/pcl/${SUBSYS_NAME}/impl/cg/geometric_consistency.hpp" ) +# The cpp files have been ordered so that files with a long compile time appear at the top, to efficiently build in parallel. Do not reorder alphabetically! set(srcs + src/cg/geometric_consistency.cpp + src/cg/hough_3d.cpp src/linemod.cpp src/quantizable_modality.cpp src/dotmod.cpp @@ -108,8 +111,6 @@ set(srcs src/hv/hv_papazov.cpp src/hv/hv_go.cpp src/hv/greedy_verification.cpp - src/cg/hough_3d.cpp - src/cg/geometric_consistency.cpp src/ransac_based/obj_rec_ransac.cpp src/ransac_based/model_library.cpp src/ransac_based/orr_octree.cpp diff --git a/recognition/include/pcl/recognition/impl/implicit_shape_model.hpp b/recognition/include/pcl/recognition/impl/implicit_shape_model.hpp index fdd87b78..1d566f23 100644 --- a/recognition/include/pcl/recognition/impl/implicit_shape_model.hpp +++ b/recognition/include/pcl/recognition/impl/implicit_shape_model.hpp @@ -1185,7 +1185,7 @@ pcl::ism::ImplicitShapeModelEstimation::alignYCoor B, A, 0.0f, 0.0f, 0.0f, 1.0f; - result = rotation_matrix_X * rotation_matrix_Z; + result.noalias() = rotation_matrix_X * rotation_matrix_Z; return (result); } diff --git a/recognition/src/ransac_based/obj_rec_ransac.cpp b/recognition/src/ransac_based/obj_rec_ransac.cpp index 25aba5c0..27f9242c 100644 --- a/recognition/src/ransac_based/obj_rec_ransac.cpp +++ b/recognition/src/ransac_based/obj_rec_ransac.cpp @@ -296,7 +296,8 @@ pcl::recognition::ObjRecRANSAC::groupHypotheses(std::list& hypot #endif // Compute the bounds for the positional discretization - float b[6]; scene_octree_.getBounds (b); + float b[6] = {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f}; + scene_octree_.getBounds (b); float enlr = scene_bounds_enlargement_factor_*std::max (std::max (b[1]-b[0], b[3]-b[2]), b[5]-b[4]); b[0] -= enlr; b[1] += enlr; b[2] -= enlr; b[3] += enlr; diff --git a/registration/include/pcl/registration/icp.h b/registration/include/pcl/registration/icp.h index dbba3109..6e06a02f 100644 --- a/registration/include/pcl/registration/icp.h +++ b/registration/include/pcl/registration/icp.h @@ -463,4 +463,5 @@ protected: extern template class pcl::IterativeClosestPoint; extern template class pcl::IterativeClosestPoint; extern template class pcl::IterativeClosestPoint; +extern template class pcl::IterativeClosestPoint; #endif // PCL_NO_PRECOMPILE diff --git a/registration/include/pcl/registration/impl/correspondence_rejection_sample_consensus.hpp b/registration/include/pcl/registration/impl/correspondence_rejection_sample_consensus.hpp index e2c68aa5..8fae7799 100644 --- a/registration/include/pcl/registration/impl/correspondence_rejection_sample_consensus.hpp +++ b/registration/include/pcl/registration/impl/correspondence_rejection_sample_consensus.hpp @@ -110,8 +110,7 @@ CorrespondenceRejectorSampleConsensus::getRemainingCorrespondences( return; } - pcl::Indices inliers; - sac.getInliers(inliers); + const auto& inliers = sac.getInliers(); if (inliers.size() < 3) { remaining_correspondences = original_correspondences; @@ -133,9 +132,8 @@ CorrespondenceRejectorSampleConsensus::getRemainingCorrespondences( inlier_indices_.push_back(index_to_correspondence[inlier]); } - // get best transformation - Eigen::VectorXf model_coefficients; - sac.getModelCoefficients(model_coefficients); + // get the best transformation + const Eigen::VectorXf& model_coefficients = sac.getModelCoefficients(); best_transformation_.row(0) = model_coefficients.segment<4>(0); best_transformation_.row(1) = model_coefficients.segment<4>(4); best_transformation_.row(2) = model_coefficients.segment<4>(8); diff --git a/registration/include/pcl/registration/impl/correspondence_rejection_sample_consensus_2d.hpp b/registration/include/pcl/registration/impl/correspondence_rejection_sample_consensus_2d.hpp index 3579fe7d..a2a767df 100644 --- a/registration/include/pcl/registration/impl/correspondence_rejection_sample_consensus_2d.hpp +++ b/registration/include/pcl/registration/impl/correspondence_rejection_sample_consensus_2d.hpp @@ -110,8 +110,7 @@ CorrespondenceRejectorSampleConsensus2D::getRemainingCorrespondences( "[pcl::registration::%s::getRemainingCorrespondences] Error refining model!\n", getClassName().c_str()); - pcl::Indices inliers; - sac.getInliers(inliers); + const auto& inliers = sac.getInliers(); if (inliers.size() < 3) { PCL_ERROR("[pcl::registration::%s::getRemainingCorrespondences] Less than 3 " @@ -131,9 +130,8 @@ CorrespondenceRejectorSampleConsensus2D::getRemainingCorrespondences( remaining_correspondences[i] = original_correspondences[index_to_correspondence[inliers[i]]]; - // get best transformation - Eigen::VectorXf model_coefficients; - sac.getModelCoefficients(model_coefficients); + // get the best transformation + const Eigen::VectorXf& model_coefficients = sac.getModelCoefficients(); best_transformation_.row(0) = model_coefficients.segment<4>(0); best_transformation_.row(1) = model_coefficients.segment<4>(4); best_transformation_.row(2) = model_coefficients.segment<4>(8); diff --git a/registration/include/pcl/registration/impl/gicp.hpp b/registration/include/pcl/registration/impl/gicp.hpp index 93fb7c81..78490b66 100644 --- a/registration/include/pcl/registration/impl/gicp.hpp +++ b/registration/include/pcl/registration/impl/gicp.hpp @@ -144,7 +144,7 @@ GeneralizedIterativeClosestPoint::computeCovar double v = 1.; // biggest 2 singular values replaced by 1 if (k == 2) // smallest singular value replaced by gicp_epsilon v = gicp_epsilon_; - cov += v * col * col.transpose(); + cov.noalias() += v * col * col.transpose(); } cloud_covariances[i] = cov; } @@ -429,8 +429,8 @@ GeneralizedIterativeClosestPoint:: else inverted_eigenvalues(i, i) = 1.0 / ev; } - delta = eigensolver.eigenvectors() * inverted_eigenvalues * - eigensolver.eigenvectors().transpose() * gradient; + delta.noalias() = eigensolver.eigenvectors() * inverted_eigenvalues * + eigensolver.eigenvectors().transpose() * gradient; // simple line search to guarantee a decrease in the function value double alpha = 1.0; @@ -542,9 +542,9 @@ GeneralizedIterativeClosestPoint:: // closes) g.head<3>() += Md; // Increment rotation gradient - p_trans_src = gicp_->base_transformation_.template cast() * p_src; + p_trans_src.noalias() = gicp_->base_transformation_.template cast() * p_src; Eigen::Vector3d p_base_src(p_trans_src[0], p_trans_src[1], p_trans_src[2]); - dCost_dR_T += p_base_src * Md.transpose(); + dCost_dR_T.noalias() += p_base_src * Md.transpose(); } g.head<3>() *= 2.0 / m; dCost_dR_T *= 2.0 / m; @@ -584,10 +584,10 @@ GeneralizedIterativeClosestPoint:: // g.head<3> ()+= 2*M*d/num_matches (we postpone 2/num_matches after the loop // closes) g.head<3>() += Md; - p_trans_src = gicp_->base_transformation_.template cast() * p_src; + p_trans_src.noalias() = gicp_->base_transformation_.template cast() * p_src; Eigen::Vector3d p_base_src(p_trans_src[0], p_trans_src[1], p_trans_src[2]); // Increment rotation gradient - dCost_dR_T += p_base_src * Md.transpose(); + dCost_dR_T.noalias() += p_base_src * Md.transpose(); } f /= static_cast(m); g.head<3>() *= (2.0 / m); @@ -661,7 +661,7 @@ GeneralizedIterativeClosestPoint:: const Eigen::Vector3d Md(M * d); // Md = M*d gradient.head<3>() += Md; // translation gradient hessian.topLeftCorner<3, 3>() += M; // translation-translation hessian - p_trans_src = base_transformation_float * p_src; + p_trans_src.noalias() = base_transformation_float * p_src; const Eigen::Vector3d p_base_src(p_trans_src[0], p_trans_src[1], p_trans_src[2]); dCost_dR_T.noalias() += p_base_src * Md.transpose(); dCost_dR_T1b += p_base_src[0] * M; @@ -790,11 +790,20 @@ GeneralizedIterativeClosestPoint:: base_transformation_ = Matrix4::Identity(); nr_iterations_ = 0; converged_ = false; - double dist_threshold = corr_dist_threshold_ * corr_dist_threshold_; pcl::Indices nn_indices(1); std::vector nn_dists(1); pcl::transformPointCloud(output, output, guess); + pcl::registration::CorrespondenceEstimation + corr_estimation; + corr_estimation.setNumberOfThreads(threads_); + // setSearchMethodSource is not necessary because we do not use + // determineReciprocalCorrespondences + corr_estimation.setSearchMethodTarget(this->getSearchMethodTarget()); + corr_estimation.setInputTarget(target_); + auto output_transformed = pcl::make_shared(); + output_transformed->resize(output.size()); + pcl::Correspondences correspondences; while (!converged_) { std::size_t cnt = 0; @@ -811,36 +820,19 @@ GeneralizedIterativeClosestPoint:: Eigen::Matrix3d R = transform_R.topLeftCorner<3, 3>(); - for (std::size_t i = 0; i < N; i++) { - PointSource query = output[i]; - query.getVector4fMap() = - transformation_.template cast() * query.getVector4fMap(); - - if (!searchForNeighbors(query, nn_indices, nn_dists)) { - PCL_ERROR("[pcl::%s::computeTransformation] Unable to find a nearest neighbor " - "in the target dataset for point %d in the source!\n", - getClassName().c_str(), - (*indices_)[i]); - return; - } - - // Check if the distance to the nearest neighbor is smaller than the user imposed - // threshold - if (nn_dists[0] < dist_threshold) { - Eigen::Matrix3d& C1 = (*input_covariances_)[i]; - Eigen::Matrix3d& C2 = (*target_covariances_)[nn_indices[0]]; - Eigen::Matrix3d& M = mahalanobis_[i]; - // M = R*C1 - M = R * C1; - // temp = M*R' + C2 = R*C1*R' + C2 - Eigen::Matrix3d temp = M * R.transpose(); - temp += C2; - // M = temp^-1 - M = temp.inverse(); - source_indices[cnt] = static_cast(i); - target_indices[cnt] = nn_indices[0]; - cnt++; - } + transformPointCloud( + output, *output_transformed, transformation_.template cast(), false); + corr_estimation.setInputSource(output_transformed); + corr_estimation.determineCorrespondences(correspondences, corr_dist_threshold_); + cnt = 0; + for (const auto& corr : correspondences) { + source_indices[cnt] = corr.index_query; + target_indices[cnt] = corr.index_match; + const Eigen::Matrix3d& C1 = (*input_covariances_)[corr.index_query]; + const Eigen::Matrix3d& C2 = (*target_covariances_)[corr.index_match]; + pcl::invert3x3SymMatrix(R * C1 * R.transpose() + C2, + mahalanobis_[corr.index_query]); + ++cnt; } // Resize to the actual number of valid correspondences source_indices.resize(cnt); @@ -895,7 +887,7 @@ GeneralizedIterativeClosestPoint:: PCL_DEBUG("[pcl::%s::computeTransformation] Convergence failed\n", getClassName().c_str()); } - final_transformation_ = previous_transformation_ * guess; + final_transformation_.noalias() = previous_transformation_ * guess; PCL_DEBUG("Transformation " "is:\n\t%5f\t%5f\t%5f\t%5f\n\t%5f\t%5f\t%5f\t%5f\n\t%5f\t%5f\t%5f\t%5f\n\t%" diff --git a/registration/include/pcl/registration/impl/icp.hpp b/registration/include/pcl/registration/impl/icp.hpp index 2b48169f..715c95dd 100644 --- a/registration/include/pcl/registration/impl/icp.hpp +++ b/registration/include/pcl/registration/impl/icp.hpp @@ -70,7 +70,7 @@ IterativeClosestPoint::transformCloud( if (!std::isfinite(pt[0]) || !std::isfinite(pt[1]) || !std::isfinite(pt[2])) continue; - pt_t = tr * pt; + pt_t.noalias() = tr * pt; memcpy(data_out + x_idx_offset_, &pt_t[0], sizeof(float)); memcpy(data_out + y_idx_offset_, &pt_t[1], sizeof(float)); @@ -83,7 +83,7 @@ IterativeClosestPoint::transformCloud( if (!std::isfinite(nt[0]) || !std::isfinite(nt[1]) || !std::isfinite(nt[2])) continue; - nt_t = rot * nt; + nt_t.noalias() = rot * nt; memcpy(data_out + nx_idx_offset_, &nt_t[0], sizeof(float)); memcpy(data_out + ny_idx_offset_, &nt_t[1], sizeof(float)); @@ -101,7 +101,7 @@ IterativeClosestPoint::transformCloud( if (!std::isfinite(pt[0]) || !std::isfinite(pt[1]) || !std::isfinite(pt[2])) continue; - pt_t = tr * pt; + pt_t.noalias() = tr * pt; memcpy(data_out + x_idx_offset_, &pt_t[0], sizeof(float)); memcpy(data_out + y_idx_offset_, &pt_t[1], sizeof(float)); diff --git a/registration/include/pcl/registration/impl/ndt.hpp b/registration/include/pcl/registration/impl/ndt.hpp index b6df6802..732beb84 100644 --- a/registration/include/pcl/registration/impl/ndt.hpp +++ b/registration/include/pcl/registration/impl/ndt.hpp @@ -121,6 +121,15 @@ NormalDistributionsTransform::computeTransform // 2009] Eigen::JacobiSVD> sv( hessian, Eigen::ComputeFullU | Eigen::ComputeFullV); +#if EIGEN_VERSION_AT_LEAST(3, 4, 0) + if (sv.info() != Eigen::ComputationInfo::Success) { + trans_likelihood_ = score / static_cast(input_->size()); + converged_ = 0; + PCL_ERROR("[%s::computeTransformation] JacobiSVD on hessian failed!\n", + getClassName().c_str()); + return; + } +#endif // Negative for maximization as opposed to minimization Eigen::Matrix delta = sv.solve(-score_gradient); diff --git a/registration/include/pcl/registration/impl/ndt_2d.hpp b/registration/include/pcl/registration/impl/ndt_2d.hpp index a4b5dd42..b54b9c8c 100644 --- a/registration/include/pcl/registration/impl/ndt_2d.hpp +++ b/registration/include/pcl/registration/impl/ndt_2d.hpp @@ -124,7 +124,7 @@ public: for (const auto& pt_index : pt_indices_) { Eigen::Vector2d p(cloud[pt_index].x, cloud[pt_index].y); sx += p; - sxx += p * p.transpose(); + sxx.noalias() += p * p.transpose(); } n_ = pt_indices_.size(); @@ -145,7 +145,7 @@ public: Eigen::Matrix2d q = solver.eigenvectors(); // set minimum smallest eigenvalue: l(0, 0) = l(1, 1) * min_covar_eigvalue_mult; - covar = q * l * q.transpose(); + covar.noalias() = q * l * q.transpose(); } covar_inv_ = covar.inverse(); } @@ -437,29 +437,28 @@ NormalDistributionsTransform2D::computeTransformation( if (score.value != 0) { // test for positive definiteness, and adjust to ensure it if necessary: - Eigen::EigenSolver solver; - solver.compute(score.hessian, false); + Eigen::SelfAdjointEigenSolver solver(score.hessian, + Eigen::EigenvaluesOnly); double min_eigenvalue = 0; for (int i = 0; i < 3; i++) - if (solver.eigenvalues()[i].real() < min_eigenvalue) - min_eigenvalue = solver.eigenvalues()[i].real(); + if (solver.eigenvalues()[i] < min_eigenvalue) + min_eigenvalue = solver.eigenvalues()[i]; // ensure "safe" positive definiteness: this is a detail missing // from the original paper if (min_eigenvalue < 0) { double lambda = 1.1 * min_eigenvalue - 1; score.hessian += Eigen::Vector3d(-lambda, -lambda, -lambda).asDiagonal(); - solver.compute(score.hessian, false); + solver.compute(score.hessian, Eigen::EigenvaluesOnly); PCL_DEBUG("[pcl::NormalDistributionsTransform2D::computeTransformation] adjust " "hessian: %f: new eigenvalues:%f %f %f\n", float(lambda), - solver.eigenvalues()[0].real(), - solver.eigenvalues()[1].real(), - solver.eigenvalues()[2].real()); + solver.eigenvalues()[0], + solver.eigenvalues()[1], + solver.eigenvalues()[2]); } - assert(solver.eigenvalues()[0].real() >= 0 && - solver.eigenvalues()[1].real() >= 0 && - solver.eigenvalues()[2].real() >= 0); + assert(solver.eigenvalues()[0] >= 0 && solver.eigenvalues()[1] >= 0 && + solver.eigenvalues()[2] >= 0); Eigen::Vector3d delta_transformation(-score.hessian.inverse() * score.grad); Eigen::Vector3d new_transformation = diff --git a/registration/include/pcl/registration/impl/ppf_registration.hpp b/registration/include/pcl/registration/impl/ppf_registration.hpp index 685c4b82..23c3298b 100644 --- a/registration/include/pcl/registration/impl/ppf_registration.hpp +++ b/registration/include/pcl/registration/impl/ppf_registration.hpp @@ -250,7 +250,7 @@ pcl::PPFRegistration::clusterPoses( PCL_DEBUG("[PPFRegistration] Clustering poses (initially got %zu poses)\n", poses.size()); // Start off by sorting the poses by the number of votes - sort(poses.begin(), poses.end(), poseWithVotesCompareFunction); + std::sort(poses.begin(), poses.end(), poseWithVotesCompareFunction); std::vector clusters; std::vector> cluster_votes; diff --git a/registration/include/pcl/registration/impl/registration.hpp b/registration/include/pcl/registration/impl/registration.hpp index db0faef5..b2469589 100644 --- a/registration/include/pcl/registration/impl/registration.hpp +++ b/registration/include/pcl/registration/impl/registration.hpp @@ -148,7 +148,7 @@ Registration::getFitnessScore(double max_range if (!input_->is_dense && !pcl::isXYZFinite(point)) continue; // Find its nearest neighbor in the target - tree_->nearestKSearch(point, 1, nn_indices, nn_dists); + tree_->nearestKSearchT(point, 1, nn_indices, nn_dists); // Deal with occlusions (incomplete targets) if (nn_dists[0] <= max_range) { @@ -216,4 +216,4 @@ Registration::align(PointCloudSource& output, deinitCompute(); } -} // namespace pcl \ No newline at end of file +} // namespace pcl diff --git a/registration/include/pcl/registration/impl/transformation_estimation_3point.hpp b/registration/include/pcl/registration/impl/transformation_estimation_3point.hpp index c4cf1671..d057b2ef 100644 --- a/registration/include/pcl/registration/impl/transformation_estimation_3point.hpp +++ b/registration/include/pcl/registration/impl/transformation_estimation_3point.hpp @@ -187,7 +187,7 @@ pcl::registration::TransformationEstimation3Point() = R; // transformation_matrix.block<3, 1>(0, 3) = source_mean.head<3>() - R * // target_mean.head<3>(); - transformation_matrix.template block<3, 1>(0, 3) = + transformation_matrix.template block<3, 1>(0, 3).noalias() = target_mean.template head<3>() - R * source_mean.template head<3>(); } diff --git a/registration/include/pcl/registration/impl/transformation_estimation_dual_quaternion.hpp b/registration/include/pcl/registration/impl/transformation_estimation_dual_quaternion.hpp index a21327ba..70a418fe 100644 --- a/registration/include/pcl/registration/impl/transformation_estimation_dual_quaternion.hpp +++ b/registration/include/pcl/registration/impl/transformation_estimation_dual_quaternion.hpp @@ -196,11 +196,11 @@ TransformationEstimationDualQuaternion:: const Eigen::Matrix A = (0.25 / static_cast(npts)) * C2.transpose() * C2 - C1; - const Eigen::EigenSolver> es(A); + const Eigen::SelfAdjointEigenSolver> es(A); ptrdiff_t i; - es.eigenvalues().real().maxCoeff(&i); - const Eigen::Matrix qmat = es.eigenvectors().col(i).real(); + es.eigenvalues().maxCoeff(&i); + const Eigen::Matrix qmat = es.eigenvectors().col(i); const Eigen::Matrix smat = -(0.5 / static_cast(npts)) * C2 * qmat; diff --git a/registration/include/pcl/registration/registration.h b/registration/include/pcl/registration/registration.h index da80847f..171b0854 100644 --- a/registration/include/pcl/registration/registration.h +++ b/registration/include/pcl/registration/registration.h @@ -665,7 +665,7 @@ protected: pcl::Indices& indices, std::vector& distances) { - int k = tree_->nearestKSearch(cloud, index, 1, indices, distances); + int k = tree_->nearestKSearchT(cloud[index], 1, indices, distances); if (k == 0) return (false); return (true); diff --git a/registration/include/pcl/registration/transformation_estimation_lm.h b/registration/include/pcl/registration/transformation_estimation_lm.h index 3af43f5c..7a2d207e 100644 --- a/registration/include/pcl/registration/transformation_estimation_lm.h +++ b/registration/include/pcl/registration/transformation_estimation_lm.h @@ -349,3 +349,13 @@ public: } // namespace pcl #include + +#if !defined(PCL_NO_PRECOMPILE) && \ + !defined(PCL_REGISTRATION_TRANSFORMATION_ESTIMATION_LM_CPP_) +extern template class pcl::registration::TransformationEstimationLM; +extern template class pcl::registration::TransformationEstimationLM; +extern template class pcl::registration::TransformationEstimationLM; +#endif // PCL_NO_PRECOMPILE diff --git a/registration/src/gicp6d.cpp b/registration/src/gicp6d.cpp index 513c4ef7..04e9b6b4 100644 --- a/registration/src/gicp6d.cpp +++ b/registration/src/gicp6d.cpp @@ -225,7 +225,7 @@ GeneralizedIterativeClosestPoint6D::computeTransformation(PointCloudSource& outp PCL_DEBUG("[pcl::%s::computeTransformation] Convergence failed\n", getClassName().c_str()); } - final_transformation_.topLeftCorner<3, 3>() = + final_transformation_.topLeftCorner<3, 3>().noalias() = previous_transformation_.topLeftCorner<3, 3>() * guess.topLeftCorner<3, 3>(); final_transformation_(0, 3) = previous_transformation_(0, 3) + guess(0, 3); final_transformation_(1, 3) = previous_transformation_(1, 3) + guess(1, 3); diff --git a/registration/src/icp.cpp b/registration/src/icp.cpp index 0ca02047..e888c322 100644 --- a/registration/src/icp.cpp +++ b/registration/src/icp.cpp @@ -48,4 +48,5 @@ template class PCL_EXPORTS pcl::IterativeClosestPoint; template class PCL_EXPORTS pcl::IterativeClosestPoint; +template class PCL_EXPORTS pcl::IterativeClosestPoint; #endif // PCL_NO_PRECOMPILE diff --git a/registration/src/transformation_estimation_lm.cpp b/registration/src/transformation_estimation_lm.cpp index 8a869e5b..96b8c052 100644 --- a/registration/src/transformation_estimation_lm.cpp +++ b/registration/src/transformation_estimation_lm.cpp @@ -36,4 +36,17 @@ * */ +#define PCL_REGISTRATION_TRANSFORMATION_ESTIMATION_LM_CPP_ #include +#include // for PCL_NO_PRECOMPILE + +#ifndef PCL_NO_PRECOMPILE +#include // for PCL_EXPORTS +#include +template class PCL_EXPORTS + pcl::registration::TransformationEstimationLM; +template class PCL_EXPORTS + pcl::registration::TransformationEstimationLM; +template class PCL_EXPORTS + pcl::registration::TransformationEstimationLM; +#endif // PCL_NO_PRECOMPILE diff --git a/sample_consensus/include/pcl/sample_consensus/impl/sac_model_circle3d.hpp b/sample_consensus/include/pcl/sample_consensus/impl/sac_model_circle3d.hpp index 8fd9458a..9f9c10ab 100644 --- a/sample_consensus/include/pcl/sample_consensus/impl/sac_model_circle3d.hpp +++ b/sample_consensus/include/pcl/sample_consensus/impl/sac_model_circle3d.hpp @@ -243,6 +243,12 @@ pcl::SampleConsensusModelCircle3D::countWithinDistance ( return (0); std::size_t nr_p = 0; + // C : Circle Center + const Eigen::Vector3d C (model_coefficients[0], model_coefficients[1], model_coefficients[2]); + // N : Circle (Plane) Normal + const Eigen::Vector3d N (model_coefficients[4], model_coefficients[5], model_coefficients[6]); + // r : Radius + const double r = model_coefficients[3]; const auto squared_threshold = threshold * threshold; // Iterate through the 3d points and calculate the distances from them to the sphere for (std::size_t i = 0; i < indices_->size (); ++i) @@ -250,12 +256,6 @@ pcl::SampleConsensusModelCircle3D::countWithinDistance ( // what i have: // P : Sample Point Eigen::Vector3d P ((*input_)[(*indices_)[i]].x, (*input_)[(*indices_)[i]].y, (*input_)[(*indices_)[i]].z); - // C : Circle Center - Eigen::Vector3d C (model_coefficients[0], model_coefficients[1], model_coefficients[2]); - // N : Circle (Plane) Normal - Eigen::Vector3d N (model_coefficients[4], model_coefficients[5], model_coefficients[6]); - // r : Radius - double r = model_coefficients[3]; Eigen::Vector3d helper_vectorPC = P - C; // 1.1. get line parameter @@ -303,7 +303,7 @@ pcl::SampleConsensusModelCircle3D::optimizeModelCoefficients ( Eigen::LevenbergMarquardt, double> lm (num_diff); Eigen::VectorXd coeff = optimized_coefficients.cast(); int info = lm.minimize (coeff); - coeff.tail(3).normalize(); // normalize the cylinder axis + coeff.tail<3>().normalize(); // normalize the cylinder axis for (Eigen::Index i = 0; i < coeff.size (); ++i) optimized_coefficients[i] = static_cast (coeff[i]); diff --git a/sample_consensus/include/pcl/sample_consensus/impl/sac_model_ellipse3d.hpp b/sample_consensus/include/pcl/sample_consensus/impl/sac_model_ellipse3d.hpp index abb0d32c..2110a2a8 100644 --- a/sample_consensus/include/pcl/sample_consensus/impl/sac_model_ellipse3d.hpp +++ b/sample_consensus/include/pcl/sample_consensus/impl/sac_model_ellipse3d.hpp @@ -16,7 +16,6 @@ #include #include -#include ////////////////////////////////////////////////////////////////////////// @@ -163,22 +162,22 @@ pcl::SampleConsensusModelEllipse3D::computeModelCoefficients (const Indi const float con_F(neigvec(5)); // Build matrix M0 - const Eigen::MatrixXf M0 = (Eigen::MatrixXf(3, 3) + const Eigen::Matrix3f M0 = (Eigen::Matrix3f() << con_F, con_D/2.0, con_E/2.0, con_D/2.0, con_A, con_B/2.0, con_E/2.0, con_B/2.0, con_C) .finished(); // Build matrix M - const Eigen::MatrixXf M = (Eigen::MatrixXf(2, 2) + const Eigen::Matrix2f M = (Eigen::Matrix2f() << con_A, con_B/2.0, con_B/2.0, con_C) .finished(); // Calculate the eigenvalues and eigenvectors of matrix M - Eigen::EigenSolver solver_M(M); + const Eigen::SelfAdjointEigenSolver solver_M(M, Eigen::EigenvaluesOnly); - Eigen::VectorXf eigvals_M = solver_M.eigenvalues().real(); + Eigen::Vector2f eigvals_M = solver_M.eigenvalues(); // Order the eigenvalues so that |lambda_0 - con_A| <= |lambda_0 - con_C| float aux_eigval(0.0); @@ -200,12 +199,12 @@ pcl::SampleConsensusModelEllipse3D::computeModelCoefficients (const Indi Eigen::Vector3f p_ctr; float aux_par(0.0); if (par_a > par_b) { - p_ctr = p0 + Rot * Eigen::Vector3f(par_h, par_k, 0.0); + p_ctr.noalias() = p0 + Rot * Eigen::Vector3f(par_h, par_k, 0.0); } else { aux_par = par_a; par_a = par_b; par_b = aux_par; - p_ctr = p0 + Rot * Eigen::Vector3f(par_k, par_h, 0.0); + p_ctr.noalias() = p0 + Rot * Eigen::Vector3f(par_k, par_h, 0.0); } // Center (x, y, z) diff --git a/sample_consensus/include/pcl/sample_consensus/impl/sac_model_plane.hpp b/sample_consensus/include/pcl/sample_consensus/impl/sac_model_plane.hpp index be51ff89..a5e13d6c 100644 --- a/sample_consensus/include/pcl/sample_consensus/impl/sac_model_plane.hpp +++ b/sample_consensus/include/pcl/sample_consensus/impl/sac_model_plane.hpp @@ -328,8 +328,6 @@ pcl::SampleConsensusModelPlane::optimizeModelCoefficients ( return; } - Eigen::Vector4f plane_parameters; - // Use Least-Squares to fit the plane through all the given sample points and find out its coefficients EIGEN_ALIGN16 Eigen::Matrix3f covariance_matrix; Eigen::Vector4f xyz_centroid; diff --git a/sample_consensus/include/pcl/sample_consensus/impl/sac_model_torus.hpp b/sample_consensus/include/pcl/sample_consensus/impl/sac_model_torus.hpp index 81cd1070..75d5fd43 100644 --- a/sample_consensus/include/pcl/sample_consensus/impl/sac_model_torus.hpp +++ b/sample_consensus/include/pcl/sample_consensus/impl/sac_model_torus.hpp @@ -213,7 +213,7 @@ pcl::SampleConsensusModelTorus::computeModelCoefficients( B << -d.dot(p0), -d.dot(p1), -d.dot(p2), -d.dot(p3); Eigen::Matrix sol; - sol = A.bdcSvd(Eigen::ComputeThinU | Eigen::ComputeThinV).solve(B); + sol = A.jacobiSvd(Eigen::ComputeThinU | Eigen::ComputeThinV).solve(B); const float r_min = -sol(0); const float D = sol(1); @@ -303,6 +303,7 @@ pcl::SampleConsensusModelTorus::selectWithinDistance( inliers.clear(); return; } + const float squared_threshold = threshold * threshold; inliers.clear(); error_sqr_dists_.clear(); inliers.reserve(indices_->size()); @@ -315,13 +316,13 @@ pcl::SampleConsensusModelTorus::selectWithinDistance( Eigen::Vector3f torus_closest; projectPointToTorus(pt, pt_n, model_coefficients, torus_closest); - const float distance = (torus_closest - pt).norm(); + const float distance = (torus_closest - pt).squaredNorm(); - if (distance < threshold) { + if (distance < squared_threshold) { // Returns the indices of the points whose distances are smaller than the // threshold inliers.push_back((*indices_)[i]); - error_sqr_dists_.push_back(distance); + error_sqr_dists_.push_back(std::sqrt(distance)); } } } @@ -335,6 +336,7 @@ pcl::SampleConsensusModelTorus::countWithinDistance( if (!isModelValid(model_coefficients)) return (0); + const float squared_threshold = threshold * threshold; std::size_t nr_p = 0; for (std::size_t i = 0; i < indices_->size(); ++i) { @@ -344,9 +346,9 @@ pcl::SampleConsensusModelTorus::countWithinDistance( Eigen::Vector3f torus_closest; projectPointToTorus(pt, pt_n, model_coefficients, torus_closest); - const float distance = (torus_closest - pt).norm(); + const float distance = (torus_closest - pt).squaredNorm(); - if (distance < threshold) { + if (distance < squared_threshold) { nr_p++; } } diff --git a/sample_consensus/include/pcl/sample_consensus/sac.h b/sample_consensus/include/pcl/sample_consensus/sac.h index 64ac36e7..302b52b0 100644 --- a/sample_consensus/include/pcl/sample_consensus/sac.h +++ b/sample_consensus/include/pcl/sample_consensus/sac.h @@ -303,18 +303,38 @@ namespace pcl inline void getModel (Indices &model) const { model = model_; } - /** \brief Return the best set of inliers found so far for this model. + /** + * \brief Return the best model found so far. + * \return the resultant model + */ + inline const Indices& + getModel() const {return model_; } + + /** \brief Return the best set of inliers found so far for this model. * \param[out] inliers the resultant set of inliers */ inline void getInliers (Indices &inliers) const { inliers = inliers_; } + /** \brief Return the best set of inliers found so far for this model. + * \return the resultant set of inliers + */ + inline const Indices& + getInliers() const {return inliers_; } + /** \brief Return the model coefficients of the best model found so far. * \param[out] model_coefficients the resultant model coefficients, as documented in \ref sample_consensus */ inline void getModelCoefficients (Eigen::VectorXf &model_coefficients) const { model_coefficients = model_coefficients_; } + /** + * \brief Return the model coefficients of the best model found so far. + * \return the resultant model coefficients + */ + inline const Eigen::VectorXf& + getModelCoefficients() const {return model_coefficients_; } + protected: /** \brief The underlying data model used (i.e. what is it that we attempt to search for). */ SampleConsensusModelPtr sac_model_; diff --git a/search/CMakeLists.txt b/search/CMakeLists.txt index d8422ab9..bf0c499f 100644 --- a/search/CMakeLists.txt +++ b/search/CMakeLists.txt @@ -22,6 +22,7 @@ set(srcs set(incs "include/pcl/${SUBSYS_NAME}/search.h" "include/pcl/${SUBSYS_NAME}/kdtree.h" + "include/pcl/${SUBSYS_NAME}/kdtree_nanoflann.h" "include/pcl/${SUBSYS_NAME}/brute_force.h" "include/pcl/${SUBSYS_NAME}/organized.h" "include/pcl/${SUBSYS_NAME}/octree.h" diff --git a/search/include/pcl/search/impl/flann_search.hpp b/search/include/pcl/search/impl/flann_search.hpp index 2026db79..3e4405df 100644 --- a/search/include/pcl/search/impl/flann_search.hpp +++ b/search/include/pcl/search/impl/flann_search.hpp @@ -374,7 +374,7 @@ pcl::search::FlannSearch::convertInputToFlannMatrix () std::size_t original_no_of_points = indices_ && !indices_->empty () ? indices_->size () : input_->size (); if (input_copied_for_flann_) - delete input_flann_->ptr(); + delete[] input_flann_->ptr(); input_copied_for_flann_ = true; index_mapping_.clear(); identity_mapping_ = true; diff --git a/search/include/pcl/search/impl/kdtree.hpp b/search/include/pcl/search/impl/kdtree.hpp index 281b1cda..8081585b 100644 --- a/search/include/pcl/search/impl/kdtree.hpp +++ b/search/include/pcl/search/impl/kdtree.hpp @@ -48,12 +48,21 @@ pcl::search::KdTree::KdTree (bool sorted) { } +template +pcl::search::KdTree::KdTree (const std::string& name, bool sorted) + : pcl::search::Search (name, sorted) +{ +} + /////////////////////////////////////////////////////////////////////////////////////////// template void pcl::search::KdTree::setPointRepresentation ( const PointRepresentationConstPtr &point_representation) { - tree_->setPointRepresentation (point_representation); + if(tree_) + tree_->setPointRepresentation (point_representation); + else + PCL_ERROR("Calling setPointRepresentation on KdTreeNanoflann that has been cast to KdTree is not possible in this PCL version. Call setPointRepresentation directly on the KdTreeNanoflann object.\n"); } /////////////////////////////////////////////////////////////////////////////////////////// @@ -68,7 +77,10 @@ pcl::search::KdTree::setSortedResults (bool sorted_results) template void pcl::search::KdTree::setEpsilon (float eps) { - tree_->setEpsilon (eps); + if(tree_) + tree_->setEpsilon (eps); + else + PCL_ERROR("Calling setEpsilon on KdTreeNanoflann that has been cast to KdTree is not possible in this PCL version. Call setEpsilon directly on the KdTreeNanoflann object.\n"); } /////////////////////////////////////////////////////////////////////////////////////////// diff --git a/search/include/pcl/search/impl/organized.hpp b/search/include/pcl/search/impl/organized.hpp index df089620..00844d02 100644 --- a/search/include/pcl/search/impl/organized.hpp +++ b/search/include/pcl/search/impl/organized.hpp @@ -371,9 +371,14 @@ pcl::search::OrganizedNeighbor::estimateProjectionMatrix () KR_ = projection_matrix_.topLeftCorner <3, 3> (); // precalculate KR * KR^T needed by calculations during nn-search - KR_KRT_ = KR_ * KR_.transpose (); + KR_KRT_.noalias() = KR_ * KR_.transpose (); + return true; +} - // final test: project a few points at known image coordinates and test if the projected coordinates are close +template bool +pcl::search::OrganizedNeighbor::testProjectionMatrix () const +{ + // test: project a few points at known image coordinates and test if the projected coordinates are close for(std::size_t i=0; i<11; ++i) { const std::size_t test_index = input_->size()*i/11u; if (!mask_[test_index]) @@ -381,7 +386,7 @@ pcl::search::OrganizedNeighbor::estimateProjectionMatrix () const auto& test_point = (*input_)[test_index]; pcl::PointXY q; if (!projectPoint(test_point, q) || std::abs(q.x-test_index%input_->width)>1 || std::abs(q.y-test_index/input_->width)>1) { - PCL_WARN ("[pcl::%s::estimateProjectionMatrix] Input dataset does not seem to be from a projective device! (point %zu (%g,%g,%g) projected to pixel coordinates (%g,%g), but actual pixel coordinates are (%zu,%zu))\n", + PCL_WARN ("[pcl::%s::testProjectionMatrix] Input dataset does not seem to be from a projective device! (point %zu (%g,%g,%g) projected to pixel coordinates (%g,%g), but actual pixel coordinates are (%zu,%zu))\n", this->getName ().c_str (), test_index, test_point.x, test_point.y, test_point.z, q.x, q.y, static_cast(test_index%input_->width), static_cast(test_index/input_->width)); return false; } diff --git a/search/include/pcl/search/impl/search.hpp b/search/include/pcl/search/impl/search.hpp index 9f24d244..8ec654a6 100644 --- a/search/include/pcl/search/impl/search.hpp +++ b/search/include/pcl/search/impl/search.hpp @@ -194,7 +194,7 @@ pcl::search::Search::sortResults ( order [idx] = static_cast (idx); Compare compare (distances); - sort (order.begin (), order.end (), compare); + std::sort (order.begin (), order.end (), compare); Indices sorted (indices.size ()); for (std::size_t idx = 0; idx < order.size (); ++idx) @@ -203,7 +203,7 @@ pcl::search::Search::sortResults ( indices = sorted; // sort the according distances. - sort (distances.begin (), distances.end ()); + std::sort (distances.begin (), distances.end ()); } #define PCL_INSTANTIATE_Search(T) template class PCL_EXPORTS pcl::search::Search; diff --git a/search/include/pcl/search/kdtree.h b/search/include/pcl/search/kdtree.h index 59018eac..fc5caddb 100644 --- a/search/include/pcl/search/kdtree.h +++ b/search/include/pcl/search/kdtree.h @@ -161,6 +161,8 @@ namespace pcl std::vector &k_sqr_distances, unsigned int max_nn = 0) const override; protected: + /** \brief This leaves the internal tree_ object uninitialized! */ + KdTree (const std::string& name, bool sorted); /** \brief A pointer to the internal KdTree object. */ KdTreePtr tree_; }; diff --git a/search/include/pcl/search/kdtree_nanoflann.h b/search/include/pcl/search/kdtree_nanoflann.h new file mode 100644 index 00000000..83db1aff --- /dev/null +++ b/search/include/pcl/search/kdtree_nanoflann.h @@ -0,0 +1,768 @@ +/* + * SPDX-License-Identifier: BSD-3-Clause + * + * Point Cloud Library (PCL) - www.pointclouds.org + * Copyright (c) 2025-, Open Perception Inc. + * + * All rights reserved + */ + +#pragma once + +#include +#if PCL_HAS_NANOFLANN || defined(DOXYGEN_ONLY) + +#include +#include + +#include + +namespace pcl { +namespace search { +namespace internal { +/** Helper for KdTreeNanoflann, serves as a dataset adaptor. + */ +template +struct PointCloudAdaptor { + PointCloudAdaptor(const T* data, + bool delete_data, + std::size_t dim, + std::size_t point_count) + : data_(data), delete_data_(delete_data), dim_(dim), point_count_(point_count) + {} + + ~PointCloudAdaptor() + { + if (delete_data_) + delete[] data_; + } + + inline void + reset_adaptor(const T* data, + bool delete_data, + std::size_t dim, + std::size_t point_count) + { + if (delete_data_) + delete[] data_; + data_ = data; + delete_data_ = delete_data; + dim_ = dim; + point_count_ = point_count; + } + + inline std::size_t + kdtree_get_point_count() const + { + return point_count_; + } + + inline T + kdtree_get_pt(const std::size_t idx, const std::size_t dim) const + { + return data_[dim_ * idx + dim]; + } + + template + bool + kdtree_get_bbox(BBOX& /* bb */) const + { + return false; + } + +private: + const T* data_; + bool delete_data_; + std::size_t dim_; + std::size_t point_count_; +}; + +/** Helper function for radiusSearch: must have a template specialization if the + * distance norm is L2 + */ +template +float +square_if_l2(float radius) +{ + return radius; +}; +template <> +float +square_if_l2, + float, + pcl::index_t>>(float radius) +{ + return radius * radius; +}; +template <> +float +square_if_l2< + nanoflann::L2_Simple_Adaptor, + float, + pcl::index_t>>(float radius) +{ + return radius * radius; +}; +} // namespace internal + +// for convenience/brevity +using L1_Adaptor = + nanoflann::L1_Adaptor, + float, + pcl::index_t>; +using L2_Adaptor = + nanoflann::L2_Adaptor, + float, + pcl::index_t>; +using L2_Simple_Adaptor = + nanoflann::L2_Simple_Adaptor, + float, + pcl::index_t>; +using SO2_Adaptor = + nanoflann::SO2_Adaptor, + float, + pcl::index_t>; +using SO3_Adaptor = + nanoflann::SO3_Adaptor, + float, + pcl::index_t>; +// TODO maybe additional adaptor with simd? + +/** @brief @b pcl::search::KdTreeNanoflann is a faster and flexible alternative to + * pcl::search::KdTree. It is based on the nanoflann library by Jose Luis Blanco-Claraco + * ( https://github.com/jlblancoc/nanoflann ). Since nanoflann is treated as an optional + * dependency to PCL, you must test the preprocessor symbol `PCL_HAS_NANOFLANN` after + * including `pcl/search/kdtree_nanoflann.h`. + * @code + * // Example 1: using KdTreeNanoflann in NormalEstimation: + * pcl::NormalEstimation ne; + * auto tree = pcl::make_shared>(); + * ne.setSearchMethod (tree); + * // rest as usual + * // Example 2: using KdTreeNanoflannn in ICP: + * pcl::IterativeClosestPoint icp; + * icp.setSearchMethodSource(pcl::make_shared>()); + * icp.setSearchMethodTarget(pcl::make_shared>()); + * // rest as usual + * // Example 3: using a L1 distance norm: + * pcl::search::KdTreeNanoflann kdtree_nanoflann; + * kdtree_nanoflann.setInputCloud (my_cloud); + * // now ready to use kdtree_nanoflann.nearestKSearch(...) and + * // kdtree_nanoflann.radiusSearch(...); + * // Example 4: using KdTreeNanoflann with features instead of 3D points: + * pcl::search::KdTreeNanoflann kdtree_nanoflann_feat; + * kdtree_nanoflann_feat.setInputCloud(my_features_cloud); + * // now ready for searching + * @endcode + * + * @tparam PointT Can be a point like pcl::PointXYZ or a feature like pcl::SHOT352 + * @tparam Dim Dimension of the KdTree to build. If set to -1, it will infer the + * dimension at runtime from the given point representation, but with a performance + * penalty. Default is 3, appropriate for all xyz point types. + * @tparam Distance The distance to use. Possible values include pcl::L1_Adaptor + * (taxicab/manhattan distance), pcl::L2_Simple_Adaptor (euclidean distance, optimized + * for few dimensions), pcl::L2_Adaptor (euclidean distance, optimized for many + * dimensions), pcl::SO2_Adaptor, pcl::SO3_Adaptor. Default is pcl::L2_Simple_Adaptor + * + * @author Markus Vieth + * @ingroup search + */ +template = 4, L2_Adaptor, L2_Simple_Adaptor>, + typename Tree = nanoflann::KDTreeSingleIndexAdaptor< + Distance, + pcl::search::internal::PointCloudAdaptor, + Dim, + pcl::index_t>> +class KdTreeNanoflann : public pcl::search::KdTree { +private: + /** The special thing here is that indices and distances are stored in _two_ vectors, + * not as a pair in _one_ vector. + */ + template + class PCLRadiusResultSet { + public: + using DistanceType = _DistanceType; + using IndexType = _IndexType; + + public: + const DistanceType radius; + + std::vector& m_indices; + std::vector& m_dists; + std::size_t max_results_; + + explicit PCLRadiusResultSet( + DistanceType radius_, + std::vector& indices, + std::vector& dists, + std::size_t max_results = std::numeric_limits::max()) + : radius(radius_), m_indices(indices), m_dists(dists), max_results_(max_results) + { + init(); + } + + void + init() + { + clear(); + if (max_results_ != std::numeric_limits::max()) { + m_indices.reserve(max_results_); + m_dists.reserve(max_results_); + } + } + void + clear() + { + m_indices.clear(); + m_dists.clear(); + } + + size_t + size() const + { + return m_indices.size(); + } + size_t + empty() const + { + return m_indices.empty(); + } + + bool + full() const + { + return true; + } + + /** + * Called during search to add an element matching the criteria. + * @return true if the search should be continued, false if the results are + * sufficient + */ + bool + addPoint(DistanceType dist, IndexType index) + { + if (dist < radius) { + m_indices.emplace_back(index); + m_dists.emplace_back(dist); + } + return (m_indices.size() < max_results_); + } + + DistanceType + worstDist() const + { + return radius; + } + + void + sort() + { + // this sort function does not do anything (yet). For now, PCLRadiusResultSet + // should only be used if the results do not have to be sorted. In the future, we + // might add sorting here if we find a really efficient way to sort both vectors + // simultaneously. + } + }; + +public: + using PointCloud = typename Search::PointCloud; + using PointCloudConstPtr = typename pcl::PointCloud::ConstPtr; + + using pcl::search::Search::indices_; + using pcl::search::Search::input_; + using pcl::search::Search::getIndices; + using pcl::search::Search::getInputCloud; + using pcl::search::Search::nearestKSearch; + using pcl::search::Search::radiusSearch; + using pcl::search::Search::sorted_results_; + using pcl::search::Search::name_; + + using Ptr = shared_ptr>; + using ConstPtr = shared_ptr>; + + using KdTreePtr = shared_ptr; + using KdTreeConstPtr = shared_ptr; + using PointRepresentationConstPtr = shared_ptr>; + + /** @brief Constructor for KdTreeNanoflann. + * + * @param[in] sorted Set to true if the nearest neighbor search results + * need to be sorted in ascending order based on their distance to the + * query point (default is false, which is faster) + * @param[in] leaf_max_size Max number of points/samples in a leaf, can be tuned to + * achieve best performance. When using this for 1nn search (e.g. correspondence + * estimation in icp/registration), then leaf_max_size=10 is usually fastest. + * Otherwise, leaf_max_size=20 is a good choice. + * @param[in] n_thread_build Number of threads for concurrent tree build (default is + * 1, meaning no concurrent build) + */ + KdTreeNanoflann(bool sorted, + std::size_t leaf_max_size, + unsigned int n_thread_build = 1) + : pcl::search::KdTree("KdTreeNanoflann", sorted) + , leaf_max_size_(leaf_max_size) + , n_thread_build_(n_thread_build) + {} + + /** @brief Constructor for KdTreeNanoflann. + * + * @param[in] sorted set to true if the nearest neighbor search results + * need to be sorted in ascending order based on their distance to the + * query point + * + */ + KdTreeNanoflann(bool sorted = false) : KdTreeNanoflann(sorted, 15, 1) {} + + /** @brief Destructor for KdTreeNanoflann. */ + ~KdTreeNanoflann() override = default; + + /** @brief Provide a pointer to the point representation to use to convert points into + * k-D vectors. If you want to use this function, it is recommended to do so _before_ + * calling setInputCloud, to avoid setting up the kd-tree twice. + * @param[in] point_representation the const shared pointer to a PointRepresentation + */ + void + setPointRepresentation(const PointRepresentationConstPtr& point_representation) + { + PCL_DEBUG("[KdTreeNanoflann::setPointRepresentation] " + "KdTreeNanoflann::setPointRepresentation called, " + "point_representation->getNumberOfDimensions()=%i, " + "point_representation->isTrivial()=%i\n", + point_representation->getNumberOfDimensions(), + point_representation->isTrivial()); + if (Dim != -1 && Dim != point_representation->getNumberOfDimensions()) { + PCL_ERROR("[KdTreeNanoflann::setPointRepresentation] The given point " + "representation uses %i dimensions, but the nr of dimensions given as " + "template parameter to KdTreeNanoflann is %i.\n", + point_representation->getNumberOfDimensions(), + Dim); + return; + } + point_representation_ = point_representation; + setUpTree(); + } + + /** @brief Get a pointer to the point representation used when converting points into + * k-D vectors. */ + inline PointRepresentationConstPtr + getPointRepresentation() const + { + return point_representation_; + } + + /** @brief Sets whether the results have to be sorted or not. + * @param[in] sorted_results set to true if the radius search results should be sorted + */ + void + setSortedResults(bool sorted_results) override + { + sorted_results_ = sorted_results; + } + + /** @brief Set the search epsilon precision (error bound) for nearest neighbors + * searches. + * @param[in] eps precision (error bound) for nearest neighbors searches + */ + void + setEpsilon(float eps) + { + eps_ = eps; + } + + /** @brief Get the search epsilon precision (error bound) for nearest neighbors + * searches. */ + inline float + getEpsilon() const + { + return eps_; + } + + /** @brief Influences the results of radiusSearch when max_nn is not set to zero. + * If the parameter max_nn of radiusSearch is set to a value greater than zero, it + * will return _at most_ that many points. If you set `use_rknn=true`, it will always + * return the points _closest_ to the query point. If you set `use_rknn=false`, it may + * return _any_ points within the radius, which can be faster. + */ + void + setUseRKNN(bool use_rknn) + { + use_rknn_ = use_rknn; + } + + /** @brief Provide a pointer to the input dataset, this will build the kd-tree. + * @param[in] cloud the const shared pointer to a PointCloud + * @param[in] indices the point indices subset that is to be used from \a cloud + */ + bool + setInputCloud(const PointCloudConstPtr& cloud, + const IndicesConstPtr& indices = IndicesConstPtr()) override + { + input_ = cloud; + indices_ = indices; + + return setUpTree(); + } + + /** @brief Get pointer to internal nanoflann tree. Use with caution. + */ + KdTreePtr + getNanoflannTree() + { + return nanoflann_tree_; + } + + /** @brief Search for the k-nearest neighbors for the given query point. + * @param[in] point the given query point + * @param[in] k the number of neighbors to search for + * @param[out] k_indices the resultant indices of the neighboring points (must be + * resized to \a k a priori!) + * @param[out] k_sqr_distances the resultant squared distances to the neighboring + * points (must be resized to \a k a priori!) + * @return number of neighbors found + */ + int + nearestKSearch(const PointT& point, + int k, + Indices& k_indices, + std::vector& k_sqr_distances) const override + { + assert(point_representation_->isValid(point) && + "Invalid (NaN, Inf) point coordinates given to nearestKSearch!"); + if (static_cast(k) > adaptor_->kdtree_get_point_count()) + k = adaptor_->kdtree_get_point_count(); + k_indices.resize(k); + k_sqr_distances.resize(k); + float* query_point = nullptr; + if (!point_representation_->isTrivial()) { + query_point = new float[point_representation_->getNumberOfDimensions()]; + point_representation_->vectorize(point, query_point); + } + // like nanoflann_tree_->knnSearch + nanoflann::KNNResultSet resultSet(k); + resultSet.init(k_indices.data(), k_sqr_distances.data()); + nanoflann_tree_->findNeighbors( + resultSet, + (query_point ? query_point : reinterpret_cast(&point)) +#if NANOFLANN_VERSION < 0x150 + , + nanoflann::SearchParams() +#endif // NANOFLANN_VERSION < 0x150 + ); + const auto search_result = resultSet.size(); + delete[] query_point; + assert(search_result == k); + + if (!identity_mapping_) { + for (auto& index : k_indices) { + index = index_mapping_[index]; + } + } + return search_result; + } + + /** @brief Search for all the nearest neighbors of the query point in a given radius. + * @param[in] point the given query point + * @param[in] radius the radius of the sphere bounding all of p_q's neighbors + * @param[out] k_indices the resultant indices of the neighboring points + * @param[out] k_sqr_distances the resultant squared distances to the neighboring + * points + * @param[in] max_nn if given, bounds the maximum returned neighbors to this value. If + * \a max_nn is set to 0 or to a number higher than the number of points in the input + * cloud, all neighbors in \a radius will be returned. + * @return number of neighbors found in radius + */ + int + radiusSearch(const PointT& point, + double radius, + Indices& k_indices, + std::vector& k_sqr_distances, + unsigned int max_nn = 0) const override + { + assert(point_representation_->isValid(point) && + "Invalid (NaN, Inf) point coordinates given to radiusSearch!"); + float* query_point = nullptr; + if (!point_representation_->isTrivial()) { + query_point = new float[point_representation_->getNumberOfDimensions()]; + point_representation_->vectorize(point, query_point); + } + if (max_nn == 0) { + // return _all_ points within radius + // Calling this->sortResults is currently slower than sorting the vector of + // nanoflann::ResultItem However, if sorted results are not requested, using + // PCLRadiusResultSet with radiusSearchCustomCallback avoids copies and is faster + if (sorted_results_) { +#if NANOFLANN_VERSION < 0x150 + std::vector> + IndicesDists; // nanoflann::ResultItem was introduced in version 1.5.0 +#else + std::vector> IndicesDists; +#endif // NANOFLANN_VERSION < 0x150 + // like nanoflann_tree_->radiusSearch + nanoflann::RadiusResultSet resultSet( + pcl::search::internal::square_if_l2(radius), IndicesDists); + nanoflann_tree_->findNeighbors( + resultSet, + (query_point ? query_point : reinterpret_cast(&point)), +#if NANOFLANN_VERSION < 0x150 + {32, eps_, sorted_results_} // first parameter is ignored in older versions, + // and removed in newer versions +#else + {eps_, sorted_results_} +#endif // NANOFLANN_VERSION < 0x150 + ); +#if NANOFLANN_VERSION < 0x160 + // before, nanoflann did not sort in findNeighbours + if (sorted_results_) + std::sort( + IndicesDists.begin(), IndicesDists.end(), nanoflann::IndexDist_Sorter()); +#endif // NANOFLANN_VERSION < 0x160 + const auto search_result = resultSet.size(); + k_indices.resize(IndicesDists.size()); + k_sqr_distances.resize(IndicesDists.size()); + for (std::size_t i = 0; i < IndicesDists.size(); ++i) { + k_indices[i] = identity_mapping_ ? IndicesDists[i].first + : index_mapping_[IndicesDists[i].first]; + k_sqr_distances[i] = IndicesDists[i].second; + } + delete[] query_point; + return search_result; + } + else { + PCLRadiusResultSet resultSet( + pcl::search::internal::square_if_l2(radius), + k_indices, + k_sqr_distances); + // like nanoflann_tree_->radiusSearchCustomCallback + nanoflann_tree_->findNeighbors( + resultSet, + (query_point ? query_point : reinterpret_cast(&point)), +#if NANOFLANN_VERSION < 0x150 + {32, eps_, sorted_results_} // first parameter is ignored in older versions, + // and removed in newer versions +#else + {eps_, sorted_results_} +#endif // NANOFLANN_VERSION < 0x150 + ); + const auto search_result = resultSet.size(); + if (!identity_mapping_) { + for (auto& index : k_indices) { + index = index_mapping_[index]; + } + } + if (sorted_results_) + this->sortResults(k_indices, k_sqr_distances); + delete[] query_point; + return search_result; + } + } + else { + // return no more than max_nn points + if (use_rknn_) { + // return points closest to query point + if (static_cast(max_nn) > adaptor_->kdtree_get_point_count()) + max_nn = adaptor_->kdtree_get_point_count(); + k_indices.resize(max_nn); + k_sqr_distances.resize(max_nn); +#if NANOFLANN_VERSION < 0x151 + // rknnSearch and RKNNResultSet were added in nanoflann 1.5.1, so do knn search + // and discard those neighbors that are outside of search radius + nanoflann::KNNResultSet resultSet(max_nn); + resultSet.init(k_indices.data(), k_sqr_distances.data()); + nanoflann_tree_->findNeighbors( + resultSet, + (query_point ? query_point : reinterpret_cast(&point)) +#if NANOFLANN_VERSION < 0x150 + , + nanoflann::SearchParams() +#endif // NANOFLANN_VERSION < 0x150 + ); + auto search_result = resultSet.size(); + for (auto iter = k_sqr_distances.rbegin(); + iter != k_sqr_distances.rend() && + *iter > pcl::search::internal::square_if_l2(radius); + ++iter) { + --search_result; + } + k_indices.resize(search_result); + k_sqr_distances.resize(search_result); +#else + // like nanoflann_tree_->rknnSearch + nanoflann::RKNNResultSet resultSet( + max_nn, pcl::search::internal::square_if_l2(radius)); + resultSet.init(k_indices.data(), k_sqr_distances.data()); + nanoflann_tree_->findNeighbors( + resultSet, + (query_point ? query_point : reinterpret_cast(&point))); + const auto search_result = resultSet.size(); + k_indices.resize(search_result); + k_sqr_distances.resize(search_result); +#endif // NANOFLANN_VERSION < 0x151 + if (!identity_mapping_) { + for (auto& index : k_indices) { + index = index_mapping_[index]; + } + } + delete[] query_point; + return search_result; + } + else { + // may return any points within the radius, can be faster + PCLRadiusResultSet resultSet( + pcl::search::internal::square_if_l2(radius), + k_indices, + k_sqr_distances, + max_nn); + // like nanoflann_tree_->radiusSearchCustomCallback + nanoflann_tree_->findNeighbors( + resultSet, + (query_point ? query_point : reinterpret_cast(&point)), +#if NANOFLANN_VERSION < 0x150 + {32, eps_, sorted_results_} // first parameter is ignored in older versions, + // and removed in newer versions +#else + {eps_, sorted_results_} +#endif // NANOFLANN_VERSION < 0x150 + ); + const auto search_result = resultSet.size(); + if (!identity_mapping_) { + for (auto& index : k_indices) { + index = index_mapping_[index]; + } + } + if (sorted_results_) + this->sortResults(k_indices, k_sqr_distances); + delete[] query_point; + return search_result; + } + } + } + +private: + /** Set up index_mapping_, adaptor_, and nanoflann_tree_, based on + * point_representation_, input_, and indices_. + */ + bool + setUpTree() + { + if (!point_representation_ || !input_ || input_->empty()) { + PCL_ERROR("[KdTreeNanoflann::setUpTree] point representation is null or input is " + "null or input is empty\n"); + return false; + } + + const std::size_t dim = point_representation_->getNumberOfDimensions(); + if (Dim != -1 && Dim != static_cast(dim)) { + PCL_ERROR("[KdTreeNanoflann::setUpTree] The given point " + "representation uses %i dimensions, but the nr of dimensions given as " + "template parameter to KdTreeNanoflann is %i.\n", + dim, + Dim); + return false; + } + index_mapping_.clear(); + if (indices_ && !indices_->empty()) { + index_mapping_.reserve(indices_->size()); + for (const auto& index : *indices_) { + if (point_representation_->isValid((*input_)[index])) { + index_mapping_.emplace_back(index); + } + } + } + else { + index_mapping_.reserve(input_->size()); + for (std::size_t index = 0; index < input_->size(); ++index) { + if (point_representation_->isValid((*input_)[index])) { + index_mapping_.emplace_back(index); + } + } + } + identity_mapping_ = true; + for (pcl::index_t index = 0; + identity_mapping_ && static_cast(index) < index_mapping_.size(); + ++index) { + identity_mapping_ = identity_mapping_ && index_mapping_[index] == index; + } + + PCL_DEBUG("[KdTreeNanoflann::setUpTree] identity_mapping_=%i, " + "point_representation_->getNumberOfDimensions()=%lu, " + "point_representation_->isTrivial ()=%i\n", + identity_mapping_ ? 1 : 0, + dim, + point_representation_->isTrivial() ? 1 : 0); + if (identity_mapping_ && point_representation_->isTrivial() && + sizeof(PointT) % sizeof(float) == 0) { + // no need to allocate memory and copy data + PCL_DEBUG("[KdTreeNanoflann::setUpTree] Mapping cloud directly, without " + "allocating memory.\n"); + adaptor_.reset(new internal::PointCloudAdaptor( + reinterpret_cast(&(*input_)[0]), + false, + sizeof(PointT) / sizeof(float), + index_mapping_.size())); + } + else { + float* data = new float[dim * index_mapping_.size()]; + float* data_itr = data; + for (auto& index : index_mapping_) { + point_representation_->vectorize((*input_)[index], data_itr); + data_itr += dim; + } + adaptor_.reset(new internal::PointCloudAdaptor( + data, true, dim, index_mapping_.size())); + } + nanoflann_tree_.reset( + new Tree(dim, + *adaptor_, +#if NANOFLANN_VERSION >= 0x150 + // concurrent tree building is possible since nanoflann 1.5.0 + {leaf_max_size_, + nanoflann::KDTreeSingleIndexAdaptorFlags::None, + n_thread_build_})); +#else + {leaf_max_size_})); + if (n_thread_build_ != 1) + PCL_WARN("[KdTreeNanoflann::setUpTree] concurrent tree building is only possible " + "with nanoflann version 1.5.0 and newer\n"); +#endif // NANOFLANN_VERSION >= 0x150 + return true; + } + + KdTreePtr nanoflann_tree_; + + shared_ptr> adaptor_; + + PointRepresentationConstPtr point_representation_{ + new DefaultPointRepresentation}; + + Indices index_mapping_; + + bool identity_mapping_{false}; + + std::size_t leaf_max_size_{15}; + + unsigned int n_thread_build_{1}; + + float eps_{0.0f}; + + bool use_rknn_{true}; +}; +} // namespace search +} // namespace pcl +#ifdef PCL_NO_PRECOMPILE +#include +#endif + +#else +//#warning "KdTreeNanoflann is not available" +#endif // PCL_HAS_NANOFLANN diff --git a/search/include/pcl/search/organized.h b/search/include/pcl/search/organized.h index 20f23841..718aa7f7 100644 --- a/search/include/pcl/search/organized.h +++ b/search/include/pcl/search/organized.h @@ -150,7 +150,7 @@ namespace pcl mask_[idx] = 1; } - return estimateProjectionMatrix () && isValid (); + return (eps_ < 0 || estimateProjectionMatrix ()) && testProjectionMatrix() && isValid (); } /** \brief Search for all neighbors of query point that are within a given radius. @@ -170,10 +170,33 @@ namespace pcl std::vector &k_sqr_distances, unsigned int max_nn = 0) const override; - /** \brief estimated the projection matrix from the input cloud. */ + /** \brief Estimate the projection matrix from the input cloud. + * \return True if it was possible to estimate the matrix, false otherwise + */ bool estimateProjectionMatrix (); + /** \brief Quick test if projection matrix and input cloud work together. + */ + bool + testProjectionMatrix () const; + + /** \brief Set projection matrix manually. Projection matrix will _not_ be estimated automatically any more. If you want to use this, call it _before_ setInputCloud. + */ + void + setProjectionMatrix (const Eigen::Matrix& projection_matrix) + { + eps_ = -1.0f; // signal to not call estimateProjectionMatrix + projection_matrix_ = projection_matrix; + // rest is the same as in estimateProjectionMatrix(): + // get left 3x3 sub matrix, which contains K * R, with K = camera matrix = [[fx s cx] [0 fy cy] [0 0 1]] + // and R being the rotation matrix + KR_ = projection_matrix_.topLeftCorner <3, 3> (); + + // precalculate KR * KR^T needed by calculations during nn-search + KR_KRT_ = KR_ * KR_.transpose (); + } + /** \brief Search for the k-nearest neighbors for a given query point. * \note limiting the maximum search radius (with setMaxDistance) can lead to a significant improvement in search speed * \param[in] p_q the given query point (\ref setInputCloud must be given a-priori!) @@ -280,7 +303,7 @@ namespace pcl Eigen::Matrix KR_KRT_; /** \brief epsilon value for the MSE of the projection matrix estimation*/ - const float eps_; + float eps_; /** \brief using only a subsample of points to calculate the projection matrix. pyramid_level_ = use down sampled cloud given by pyramid_level_*/ const unsigned pyramid_level_; diff --git a/segmentation/include/pcl/segmentation/impl/cpc_segmentation.hpp b/segmentation/include/pcl/segmentation/impl/cpc_segmentation.hpp index f1aca882..04c34812 100644 --- a/segmentation/include/pcl/segmentation/impl/cpc_segmentation.hpp +++ b/segmentation/include/pcl/segmentation/impl/cpc_segmentation.hpp @@ -159,12 +159,11 @@ pcl::CPCSegmentation::applyCuttingPlane (std::uint32_t depth_levels_left continue; } - Eigen::VectorXf model_coefficients; - weight_sac.getModelCoefficients (model_coefficients); + Eigen::VectorXf model_coefficients = weight_sac.getModelCoefficients (); model_coefficients[3] += std::numeric_limits::epsilon (); - weight_sac.getInliers (*support_indices); + *support_indices = weight_sac.getInliers (); // the support_indices which are actually cut (if not locally constrain: cut_support_indices = support_indices pcl::Indices cut_support_indices; diff --git a/segmentation/include/pcl/segmentation/impl/sac_segmentation.hpp b/segmentation/include/pcl/segmentation/impl/sac_segmentation.hpp index e701b5ef..817bf746 100644 --- a/segmentation/include/pcl/segmentation/impl/sac_segmentation.hpp +++ b/segmentation/include/pcl/segmentation/impl/sac_segmentation.hpp @@ -108,11 +108,10 @@ pcl::SACSegmentation::segment (PointIndices &inliers, ModelCoefficients } // Get the model inliers - sac_->getInliers (inliers.indices); + inliers.indices = sac_->getInliers (); // Get the model coefficients - Eigen::VectorXf coeff (model_->getModelSize ()); - sac_->getModelCoefficients (coeff); + Eigen::VectorXf coeff = sac_->getModelCoefficients (); // If the user needs optimized coefficients if (optimize_coefficients_) diff --git a/segmentation/include/pcl/segmentation/region_3d.h b/segmentation/include/pcl/segmentation/region_3d.h index 3429579d..4ffcf3f5 100644 --- a/segmentation/include/pcl/segmentation/region_3d.h +++ b/segmentation/include/pcl/segmentation/region_3d.h @@ -115,7 +115,7 @@ namespace pcl unsigned count_; /** \brief The mean curvature of the region. */ - float curvature_; + float curvature_{0.0f}; public: PCL_MAKE_ALIGNED_OPERATOR_NEW diff --git a/segmentation/src/grabcut_segmentation.cpp b/segmentation/src/grabcut_segmentation.cpp index f15aef82..ca8dc605 100644 --- a/segmentation/src/grabcut_segmentation.cpp +++ b/segmentation/src/grabcut_segmentation.cpp @@ -617,10 +617,18 @@ pcl::segmentation::grabcut::GaussianFitter::fit (Gaussian& g, std::size_t total_ { // Compute eigenvalues and vectors using SVD Eigen::JacobiSVD svd (g.covariance, Eigen::ComputeFullU); - // Store highest eigenvalue - g.eigenvalue = svd.singularValues ()[0]; - // Store corresponding eigenvector - g.eigenvector = svd.matrixU ().col (0); +#if EIGEN_VERSION_AT_LEAST(3, 4, 0) + if (svd.info() == Eigen::ComputationInfo::Success) { +#endif + // Store highest eigenvalue + g.eigenvalue = svd.singularValues ()[0]; + // Store corresponding eigenvector + g.eigenvector = svd.matrixU ().col (0); +#if EIGEN_VERSION_AT_LEAST(3, 4, 0) + } else { + PCL_WARN("[grabcut::GaussianFitter::fit] Eigen::JacobiSVD was unsuccessful!\n"); + } +#endif } } } diff --git a/simulation/src/glsl_shader.cpp b/simulation/src/glsl_shader.cpp index 4eed218b..e45c609a 100644 --- a/simulation/src/glsl_shader.cpp +++ b/simulation/src/glsl_shader.cpp @@ -160,7 +160,28 @@ pcl::simulation::gllib::getGLError() GLenum error = glGetError(); while (error != GL_NO_ERROR) { last_error = error; - std::cout << "Error: OpenGL: " << gluErrorString(error) << std::endl; + switch (error) { + case GL_INVALID_ENUM: + std::cout << "Error: OpenGL: GL_INVALID_ENUM" << std::endl; + break; + case GL_INVALID_VALUE: + std::cout << "Error: OpenGL: GL_INVALID_VALUE" << std::endl; + break; + case GL_INVALID_OPERATION: + std::cout << "Error: OpenGL: GL_INVALID_OPERATION" << std::endl; + break; + case GL_STACK_OVERFLOW: + std::cout << "Error: OpenGL: GL_STACK_OVERFLOW" << std::endl; + break; + case GL_STACK_UNDERFLOW: + std::cout << "Error: OpenGL: GL_STACK_UNDERFLOW" << std::endl; + break; + case GL_OUT_OF_MEMORY: + std::cout << "Error: OpenGL: GL_OUT_OF_MEMORY" << std::endl; + break; + default: + std::cout << "Error: OpenGL: Unknown error" << std::endl; + } error = glGetError(); } return last_error; diff --git a/surface/include/pcl/surface/3rdparty/poisson4/octree_poisson.hpp b/surface/include/pcl/surface/3rdparty/poisson4/octree_poisson.hpp index e7f45b65..0b2407f9 100644 --- a/surface/include/pcl/surface/3rdparty/poisson4/octree_poisson.hpp +++ b/surface/include/pcl/surface/3rdparty/poisson4/octree_poisson.hpp @@ -181,10 +181,10 @@ namespace pcl int OctNode::maxDepth(void) const{ if(!children){return 0;} else{ - int c,d; + int c = std::numeric_limits::lowest(); for(int i=0;ic){c=d;} + const int d=children[i].maxDepth(); + if(d>c){c=d;} } return c+1; } diff --git a/surface/include/pcl/surface/impl/concave_hull.hpp b/surface/include/pcl/surface/impl/concave_hull.hpp index 346daad2..d769a656 100644 --- a/surface/include/pcl/surface/impl/concave_hull.hpp +++ b/surface/include/pcl/surface/impl/concave_hull.hpp @@ -617,6 +617,9 @@ pcl::ConcaveHull::performReconstruction (std::vector &p template void pcl::ConcaveHull::getHullPointIndices (pcl::PointIndices &hull_point_indices) const { + if (!keep_information_) { + PCL_WARN("[pcl::ConcaveHull::getHullPointIndices] You need to call setKeepInformation(true) before reconstructing!\n"); + } hull_point_indices = hull_indices_; } diff --git a/surface/include/pcl/surface/impl/gp3.hpp b/surface/include/pcl/surface/impl/gp3.hpp index e93b92b3..2b5dcf65 100644 --- a/surface/include/pcl/surface/impl/gp3.hpp +++ b/surface/include/pcl/surface/impl/gp3.hpp @@ -91,9 +91,6 @@ pcl::GreedyProjectionTriangulation::reconstructPolygons (std::vector

::performUpsampling (PointCloudOut & p.y = pos[1]; p.z = pos[2]; - pcl::Indices nn_indices; - std::vector nn_dists; + pcl::Indices nn_indices (1); + std::vector nn_dists (1); tree_->nearestKSearch (p, 1, nn_indices, nn_dists); const auto input_index = nn_indices.front (); @@ -796,8 +796,8 @@ pcl::MLSResult::computeMLSSurface (const pcl::PointCloud &cloud, // Computing coefficients const Eigen::MatrixXd P_weight = P * weight_vec.asDiagonal(); // size will be (nr_coeff_, nn_indices.size ()); - P_weight_Pt = P_weight * P.transpose (); - c_vec = P_weight * f_vec; + P_weight_Pt.noalias() = P_weight * P.transpose (); + c_vec.noalias() = P_weight * f_vec; P_weight_Pt.llt ().solveInPlace (c_vec); } } diff --git a/surface/src/3rdparty/opennurbs/opennurbs_bezier.cpp b/surface/src/3rdparty/opennurbs/opennurbs_bezier.cpp index 7cb6a3a1..f842be07 100644 --- a/surface/src/3rdparty/opennurbs/opennurbs_bezier.cpp +++ b/surface/src/3rdparty/opennurbs/opennurbs_bezier.cpp @@ -2984,7 +2984,7 @@ bool ON_ChangeRationalBezierCurveWeights( return false; if ( i0 == i1 && w0 != w1 ) return false; - if ( (w0 < 0.0 && w1 > 0.0) || (w0 > 0.0 && w0 < 0.0) ) + if ( (w0 < 0.0 && w1 > 0.0) || (w0 > 0.0 && w1 < 0.0) ) return false; if (i0 > i1) { diff --git a/surface/src/3rdparty/opennurbs/opennurbs_nurbscurve.cpp b/surface/src/3rdparty/opennurbs/opennurbs_nurbscurve.cpp index 8fa2d16b..2a61eb3d 100644 --- a/surface/src/3rdparty/opennurbs/opennurbs_nurbscurve.cpp +++ b/surface/src/3rdparty/opennurbs/opennurbs_nurbscurve.cpp @@ -3598,7 +3598,7 @@ bool ON_NurbsCurve::ChangeEndWeights(double w0, double w1) { if ( !ON_IsValid(w0) || !ON_IsValid(w1) || 0.0 == w0 || 0.0 == w1 ) return false; - if ( (w0 < 0.0 && w1 > 0.0) || (w0 > 0.0 && w0 < 0.0) ) + if ( (w0 < 0.0 && w1 > 0.0) || (w0 > 0.0 && w1 < 0.0) ) return false; if (!ClampEnd(2)) @@ -3633,7 +3633,7 @@ bool ON_ChangeRationalNurbsCurveEndWeights( if ( !ON_IsValid(w0) || !ON_IsValid(w1) || 0.0 == w0 || 0.0 == w1 ) return false; - if ( (w0 < 0.0 && w1 > 0.0) || (w0 > 0.0 && w0 < 0.0) ) + if ( (w0 < 0.0 && w1 > 0.0) || (w0 > 0.0 && w1 < 0.0) ) return false; if ( !ON_ClampKnotVector( dim+1, order, cv_count, cvstride, cv, knot, 2 ) ) diff --git a/surface/src/on_nurbs/closing_boundary.cpp b/surface/src/on_nurbs/closing_boundary.cpp index c3b22724..4bb1637e 100644 --- a/surface/src/on_nurbs/closing_boundary.cpp +++ b/surface/src/on_nurbs/closing_boundary.cpp @@ -233,7 +233,6 @@ ClosingBoundary::sampleUniform (ON_NurbsSurface *nurbs, vector_vec3d &point_list double maxV = nurbs->Knot (1, nurbs->KnotCount (1) - 1); Eigen::Vector2d params; - Eigen::Vector3d point; double points[3]; @@ -258,7 +257,6 @@ ClosingBoundary::sampleRandom (ON_NurbsSurface *nurbs, vector_vec3d &point_list, double maxV = nurbs->Knot (1, nurbs->KnotCount (1) - 1); Eigen::Vector2d params; - Eigen::Vector3d point; double points[3]; @@ -283,7 +281,6 @@ ClosingBoundary::sampleFromBoundary (ON_NurbsSurface *nurbs, vector_vec3d &point double maxV = nurbs->Knot (1, nurbs->KnotCount (1) - 1); Eigen::Vector2d params; - Eigen::Vector3d point; double points[3]; diff --git a/surface/src/on_nurbs/sequential_fitter.cpp b/surface/src/on_nurbs/sequential_fitter.cpp index 10433490..9cdb6bf2 100644 --- a/surface/src/on_nurbs/sequential_fitter.cpp +++ b/surface/src/on_nurbs/sequential_fitter.cpp @@ -184,7 +184,7 @@ bool SequentialFitter::is_back_facing (const Eigen::Vector3d &v0, const Eigen::Vector3d &v1, const Eigen::Vector3d &v2, const Eigen::Vector3d &) { - Eigen::Vector3d e1, e2, e3; + Eigen::Vector3d e1, e2; e1 = v1 - v0; e2 = v2 - v0; diff --git a/surface/src/on_nurbs/triangulation.cpp b/surface/src/on_nurbs/triangulation.cpp index 9951cdb5..86e31e8d 100644 --- a/surface/src/on_nurbs/triangulation.cpp +++ b/surface/src/on_nurbs/triangulation.cpp @@ -296,8 +296,6 @@ Triangulation::convertTrimmedSurface2PolygonMesh (const ON_NurbsSurface &nurbs, for (auto &v : *cloud) { - Eigen::Vector3d tu, tv; - double point[3]; nurbs.Evaluate (v.x, v.y, 0, 3, point); diff --git a/test/common/test_centroid.cpp b/test/common/test_centroid.cpp index 93e3b5a3..36434496 100644 --- a/test/common/test_centroid.cpp +++ b/test/common/test_centroid.cpp @@ -845,9 +845,6 @@ TEST (PCL, computeCentroidAndOBB) PointXYZ point; Indices indices; Eigen::Vector3f centroid = Eigen::Vector3f::Random(); - Eigen::Vector3f major_axis; - Eigen::Vector3f middle_axis; - Eigen::Vector3f minor_axis; Eigen::Matrix obb_position; Eigen::Matrix obb_dimensions; Eigen::Matrix3f obb_rotational_matrix= Eigen::Matrix3f::Random(); diff --git a/test/common/test_copy_point.cpp b/test/common/test_copy_point.cpp index 20cfcd89..efcc9d5b 100644 --- a/test/common/test_copy_point.cpp +++ b/test/common/test_copy_point.cpp @@ -170,6 +170,55 @@ TEST (CopyPointTest, DifferentTypesWithSameColor) } } +namespace custom { + struct MyPoint { + float x, y, z, w; + double intensity; + }; + struct MyPoint2 { + double x, y, z, w; + }; +} + +POINT_CLOUD_REGISTER_POINT_STRUCT (custom::MyPoint, + (float, x, x) + (float, y, y) + (float, z, z) + (double, intensity, intensity) +) +POINT_CLOUD_REGISTER_POINT_STRUCT (custom::MyPoint2, + (double, x, x) + (double, y, y) + (double, z, z) +) + +TEST(CopyPointTest, SameFieldNameDifferentDatatype) +{ + // in p1 the intensity field is double, while in p2 it is float + custom::MyPoint p1; + pcl::PointXYZI p2; + p1.x = 1.0; + p1.y = 2.0; + p1.z = 3.0; + p1.intensity = 5.0; + pcl::copyPoint(p1, p2); + EXPECT_EQ(p1.x, p2.x); + EXPECT_EQ(p1.y, p2.y); + EXPECT_EQ(p1.z, p2.z); + EXPECT_EQ(p1.intensity, p2.intensity); + + // in p3 xyz are float, while in p4 they are double + pcl::PointXYZ p3; + custom::MyPoint2 p4; + p3.x = 10.0; + p3.y = 11.0; + p3.z = 12.0; + pcl::copyPoint(p3, p4); + EXPECT_EQ(p3.x, p4.x); + EXPECT_EQ(p3.y, p4.y); + EXPECT_EQ(p3.z, p4.z); +} + int main (int argc, char **argv) { diff --git a/test/io/test_grabbers.cpp b/test/io/test_grabbers.cpp index 732c0faf..df03f048 100644 --- a/test/io/test_grabbers.cpp +++ b/test/io/test_grabbers.cpp @@ -5,6 +5,7 @@ #include #include +#include #include #include #include diff --git a/test/io/test_io.cpp b/test/io/test_io.cpp index caa95123..65676705 100644 --- a/test/io/test_io.cpp +++ b/test/io/test_io.cpp @@ -1730,6 +1730,30 @@ TYPED_TEST (AutoIOTest, AutoLoadCloudFiles) remove ("test_autoio.ifs"); } +TEST(PCL, IFS) +{ + // Write a cloud to an IFS file and check if it is the same after loading + pcl::PointCloud::Ptr cloud(new pcl::PointCloud); + cloud->push_back(pcl::PointXYZ(1.0, 2.0, 3.0)); + cloud->push_back(pcl::PointXYZ(4.0, 5.0, 6.0)); + + pcl::io::saveIFSFile("test.ifs", *cloud); + + pcl::PointCloud::Ptr loaded(new pcl::PointCloud); + pcl::io::loadIFSFile("test.ifs", *loaded); + + EXPECT_EQ(cloud->size(), loaded->size()); + for (size_t i = 0; i < cloud->size(); ++i) + { + const auto& src = cloud->points[i]; + const auto& dst = loaded->points[i]; + EXPECT_EQ(src.x, dst.x); + EXPECT_EQ(src.y, dst.y); + EXPECT_EQ(src.z, dst.z); + } + remove("test.ifs"); +} + /* ---[ */ int main (int argc, char** argv) diff --git a/test/search/CMakeLists.txt b/test/search/CMakeLists.txt index 22f95007..3729072b 100644 --- a/test/search/CMakeLists.txt +++ b/test/search/CMakeLists.txt @@ -18,6 +18,13 @@ PCL_ADD_TEST(flann_search test_flann_search FILES test_flann_search.cpp LINK_WITH pcl_gtest pcl_search pcl_kdtree) +if(TARGET nanoflann::nanoflann) +PCL_ADD_TEST(kdtree_nanoflann_search test_kdtree_nanoflann_search + FILES test_kdtree_nanoflann.cpp + LINK_WITH pcl_gtest pcl_common pcl_search pcl_io pcl_features + ARGUMENTS "${PCL_SOURCE_DIR}/test/bun0.pcd") +endif() + PCL_ADD_TEST(organized_neighbor test_organized_search FILES test_organized.cpp LINK_WITH pcl_gtest pcl_search pcl_kdtree) diff --git a/test/search/test_kdtree_nanoflann.cpp b/test/search/test_kdtree_nanoflann.cpp new file mode 100644 index 00000000..da021bfd --- /dev/null +++ b/test/search/test_kdtree_nanoflann.cpp @@ -0,0 +1,797 @@ +/* + * SPDX-License-Identifier: BSD-3-Clause + * + * Point Cloud Library (PCL) - www.pointclouds.org + * Copyright (c) 2025-, Open Perception Inc. + * + * All rights reserved + */ + +#define PCL_NO_PRECOMPILE 1 // for MyPoint instantiations +#include +#include // for copyPointCloud +#include +#include +#include +#include +#include // for pcl::search::KdTree +#include // for pcl::search::KdTreeNanoflann +#include +#include +#include + +#include + +namespace pcl_tests { +inline double +squared_point_distance(const pcl::Narf36& p1, const pcl::Narf36& p2) +{ + double dist = 0.0; + for (std::size_t i = 0; i < 36; ++i) + dist += std::pow(static_cast(p1.descriptor[i]) - + static_cast(p2.descriptor[i]), + 2); + return dist; +} +} // namespace pcl_tests + +using namespace pcl; + +// many of the tests are copied and adapted form test/search/test_flann_search.cpp and +// test/kdtree/test_kdtree.cpp + +PointCloud cloud, cloud_big, bun0_cloud; + +void +init() +{ + float resolution = 0.1f; + for (float z = -0.5f; z <= 0.5f; z += resolution) + for (float y = -0.5f; y <= 0.5f; y += resolution) + for (float x = -0.5f; x <= 0.5f; x += resolution) + cloud.emplace_back(static_cast(rand()) / (RAND_MAX + 1.0) - 0.5, + static_cast(rand()) / (RAND_MAX + 1.0) - 0.5, + static_cast(rand()) / (RAND_MAX + 1.0) - 0.5); + cloud.width = cloud.size(); + cloud.height = 1; + + // Randomly create a new point cloud, use points.emplace_back + cloud_big.width = 640 * 480; + cloud_big.height = 1; + for (std::size_t i = 0; i < cloud_big.width * cloud_big.height; ++i) + cloud_big.points.emplace_back(static_cast(1024 * rand() / (RAND_MAX + 1.0)), + static_cast(1024 * rand() / (RAND_MAX + 1.0)), + static_cast(1024 * rand() / (RAND_MAX + 1.0))); +} + +TEST(PCL, KdTreeNanoflann_nearestKSearch) +{ + auto kdtree = pcl::make_shared>(); + kdtree->setInputCloud(cloud.makeShared()); + EXPECT_EQ(kdtree->getEpsilon(), 0.0f); + kdtree->setEpsilon(1.23f); + EXPECT_EQ(kdtree->getEpsilon(), 1.23f); + kdtree->setEpsilon(0.0f); + PointXYZ test_point(0.01f, 0.01f, 0.01f); + unsigned int no_of_neighbors = 20; + std::multimap sorted_brute_force_result; + for (std::size_t i = 0; i < cloud.size(); ++i) { + float distance = euclideanDistance(cloud[i], test_point); + sorted_brute_force_result.insert(std::make_pair(distance, static_cast(i))); + } + float max_dist = 0.0f; + unsigned int counter = 0; + for (auto it = sorted_brute_force_result.begin(); + it != sorted_brute_force_result.end() && counter < no_of_neighbors; + ++it) { + max_dist = std::max(max_dist, it->first); + ++counter; + } + + pcl::Indices k_indices; + k_indices.resize(no_of_neighbors); + std::vector k_distances; + k_distances.resize(no_of_neighbors); + + kdtree->nearestKSearch(test_point, no_of_neighbors, k_indices, k_distances); + + EXPECT_EQ(k_indices.size(), no_of_neighbors); + + // Check if all found neighbors have distance smaller than max_dist + for (const auto& k_index : k_indices) { + const PointXYZ& point = cloud[k_index]; + bool ok = euclideanDistance(test_point, point) <= max_dist; + if (!ok) + ok = (std::abs(euclideanDistance(test_point, point)) - max_dist) <= 1e-6; + EXPECT_TRUE(ok); + } + + kdtree->setUseRKNN(true); + pcl::Indices k_indices_rknn; + std::vector k_distances_rknn; + // first test with search radius bigger than farthest neighbor, results should be the + // same + kdtree->radiusSearch(test_point, + max_dist + std::numeric_limits::epsilon(), + k_indices_rknn, + k_distances_rknn, + no_of_neighbors); + EXPECT_EQ(k_indices_rknn.size(), k_indices.size()); + EXPECT_EQ(k_distances_rknn.size(), k_distances.size()); + for (std::size_t i = 0; + i < std::min(k_indices.size(), k_indices_rknn.size()); + ++i) { + EXPECT_EQ(k_indices[i], k_indices_rknn[i]); + EXPECT_EQ(k_distances[i], k_distances_rknn[i]); + } + // then test with search radius slightly smaller than farthest neighbor, should have + // one neighbor less + kdtree->radiusSearch(test_point, + max_dist - std::numeric_limits::epsilon(), + k_indices_rknn, + k_distances_rknn, + no_of_neighbors); + EXPECT_EQ(k_indices_rknn.size() + 1, k_indices.size()); + EXPECT_EQ(k_distances_rknn.size() + 1, k_distances.size()); + for (std::size_t i = 0; + i < std::min(k_indices.size(), k_indices_rknn.size()); + ++i) { + EXPECT_EQ(k_indices[i], k_indices_rknn[i]); + EXPECT_EQ(k_distances[i], k_distances_rknn[i]); + } +} + +/* Test the templated NN search (for different query point types) */ +TEST(PCL, KdTreeNanoflannSearch_differentPointT) +{ + + unsigned int no_of_neighbors = 20; + + pcl::search::KdTreeNanoflann kdtree; + kdtree.setInputCloud(cloud_big.makeShared()); + + PointCloud cloud_rgb; + + copyPointCloud(cloud_big, cloud_rgb); + + std::vector> dists; + std::vector indices; + kdtree.nearestKSearchT(cloud_rgb, pcl::Indices(), no_of_neighbors, indices, dists); + + pcl::Indices k_indices; + k_indices.resize(no_of_neighbors); + std::vector k_distances; + k_distances.resize(no_of_neighbors); + + for (std::size_t i = 0; i < cloud_rgb.size(); ++i) { + kdtree.nearestKSearch(cloud_big[i], no_of_neighbors, k_indices, k_distances); + EXPECT_EQ(k_indices.size(), indices[i].size()); + EXPECT_EQ(k_distances.size(), dists[i].size()); + for (std::size_t j = 0; j < no_of_neighbors; j++) { + EXPECT_TRUE(k_indices[j] == indices[i][j] || k_distances[j] == dists[i][j]); + } + } +} + +/* Test for KdTreeNanoflann nearestKSearch with multiple query points */ +TEST(PCL, KdTreeNanoflann_multipointKnnSearch) +{ + + unsigned int no_of_neighbors = 20; + + pcl::search::KdTreeNanoflann kdtree; + kdtree.setInputCloud(cloud_big.makeShared()); + + std::vector> dists; + std::vector indices; + kdtree.nearestKSearch(cloud_big, pcl::Indices(), no_of_neighbors, indices, dists); + + pcl::Indices k_indices; + k_indices.resize(no_of_neighbors); + std::vector k_distances; + k_distances.resize(no_of_neighbors); + + for (std::size_t i = 0; i < cloud_big.size(); ++i) { + kdtree.nearestKSearch(cloud_big[i], no_of_neighbors, k_indices, k_distances); + EXPECT_EQ(k_indices.size(), indices[i].size()); + EXPECT_EQ(k_distances.size(), dists[i].size()); + for (std::size_t j = 0; j < no_of_neighbors; j++) { + EXPECT_TRUE(k_indices[j] == indices[i][j] || k_distances[j] == dists[i][j]); + } + } +} + +/* Test for KdTreeNanoflann nearestKSearch with multiple query points */ +TEST(PCL, KdTreeNanoflann_knnByIndex) +{ + + unsigned int no_of_neighbors = 3; + + pcl::search::KdTreeNanoflann kdtree; + kdtree.setInputCloud(cloud_big.makeShared()); + + std::vector> dists; + std::vector indices; + pcl::Indices query_indices; + for (std::size_t i = 0; i < cloud_big.size(); i += 2) { + query_indices.push_back(static_cast(i)); + } + kdtree.nearestKSearch(cloud_big, query_indices, no_of_neighbors, indices, dists); + + pcl::Indices k_indices; + k_indices.resize(no_of_neighbors); + std::vector k_distances; + k_distances.resize(no_of_neighbors); + + for (std::size_t i = 0; i < query_indices.size(); ++i) { + kdtree.nearestKSearch(cloud_big[2 * i], no_of_neighbors, k_indices, k_distances); + EXPECT_EQ(k_indices.size(), indices[i].size()); + EXPECT_EQ(k_distances.size(), dists[i].size()); + for (std::size_t j = 0; j < no_of_neighbors; j++) { + EXPECT_TRUE(k_indices[j] == indices[i][j] || k_distances[j] == dists[i][j]); + } + kdtree.nearestKSearch( + cloud_big, query_indices[i], no_of_neighbors, k_indices, k_distances); + EXPECT_EQ(k_indices.size(), indices[i].size()); + EXPECT_EQ(k_distances.size(), dists[i].size()); + for (std::size_t j = 0; j < no_of_neighbors; j++) { + EXPECT_TRUE(k_indices[j] == indices[i][j] || k_distances[j] == dists[i][j]); + } + } +} + +TEST(PCL, KdTreeNanoflann_compareToKdTreeFlann) +{ + + int no_of_neighbors = 3; + pcl::Indices k_indices; + k_indices.resize(no_of_neighbors); + std::vector k_distances; + k_distances.resize(no_of_neighbors); + + pcl::search::Search*nanoflann_search, *kdtree_search; + + PointCloud::Ptr pc = cloud_big.makeShared(); + { + ScopeTime scopeTime("KdTreeNanoflann build"); + nanoflann_search = new pcl::search::KdTreeNanoflann; + nanoflann_search->setInputCloud(pc); + } + + { + ScopeTime scopeTime("kdtree build"); + kdtree_search = new pcl::search::KdTree(); + kdtree_search->setInputCloud(pc); + } + + { + ScopeTime scopeTime("KdTreeNanoflann nearestKSearch"); + for (const auto& point : cloud_big.points) + nanoflann_search->nearestKSearch(point, no_of_neighbors, k_indices, k_distances); + } + { + ScopeTime scopeTime("kd tree nearestKSearch"); + for (const auto& point : cloud_big.points) + kdtree_search->nearestKSearch(point, no_of_neighbors, k_indices, k_distances); + } + + std::vector indices_nanoflann; + std::vector> dists_nanoflann; + std::vector indices_tree; + std::vector> dists_tree; + indices_nanoflann.resize(cloud_big.size()); + dists_nanoflann.resize(cloud_big.size()); + indices_tree.resize(cloud_big.size()); + dists_tree.resize(cloud_big.size()); + for (std::size_t i = 0; i < cloud_big.size(); ++i) { + indices_nanoflann[i].resize(no_of_neighbors); + dists_nanoflann[i].resize(no_of_neighbors); + indices_tree[i].resize(no_of_neighbors); + dists_tree[i].resize(no_of_neighbors); + } + + { + ScopeTime scopeTime("KdTreeNanoflann multi nearestKSearch"); + nanoflann_search->nearestKSearch( + cloud_big, pcl::Indices(), no_of_neighbors, indices_nanoflann, dists_nanoflann); + } + { + ScopeTime scopeTime("kd tree multi nearestKSearch"); + kdtree_search->nearestKSearch( + cloud_big, pcl::Indices(), no_of_neighbors, indices_tree, dists_tree); + } + + ASSERT_EQ(indices_nanoflann.size(), dists_nanoflann.size()); + ASSERT_EQ(indices_nanoflann.size(), indices_tree.size()); + ASSERT_EQ(indices_nanoflann.size(), dists_tree.size()); + + for (std::size_t i = 0; i < indices_nanoflann.size(); i++) { + ASSERT_EQ(indices_nanoflann[i].size(), no_of_neighbors); + ASSERT_EQ(indices_tree[i].size(), no_of_neighbors); + ASSERT_EQ(dists_nanoflann[i].size(), no_of_neighbors); + ASSERT_EQ(dists_tree[i].size(), no_of_neighbors); + for (int j = 0; j < no_of_neighbors; j++) { + + ASSERT_TRUE(indices_nanoflann[i][j] == indices_tree[i][j] || + dists_nanoflann[i][j] == dists_tree[i][j]); + } + } + + pcl::Indices query_indices; + for (std::size_t i = 0; i < cloud_big.size(); i += 2) + query_indices.push_back(static_cast(i)); + + { + ScopeTime scopeTime("KdTreeNanoflann multi nearestKSearch with indices"); + nanoflann_search->nearestKSearch( + cloud_big, query_indices, no_of_neighbors, indices_nanoflann, dists_nanoflann); + } + { + ScopeTime scopeTime("kd tree multi nearestKSearch with indices"); + kdtree_search->nearestKSearch( + cloud_big, query_indices, no_of_neighbors, indices_tree, dists_tree); + } + ASSERT_EQ(indices_nanoflann.size(), dists_nanoflann.size()); + ASSERT_EQ(indices_nanoflann.size(), indices_tree.size()); + ASSERT_EQ(indices_nanoflann.size(), dists_tree.size()); + + for (std::size_t i = 0; i < indices_nanoflann.size(); i++) { + ASSERT_EQ(indices_nanoflann[i].size(), no_of_neighbors); + ASSERT_EQ(indices_tree[i].size(), no_of_neighbors); + ASSERT_EQ(dists_nanoflann[i].size(), no_of_neighbors); + ASSERT_EQ(dists_tree[i].size(), no_of_neighbors); + for (int j = 0; j < no_of_neighbors; j++) { + ASSERT_TRUE(indices_nanoflann[i][j] == indices_tree[i][j] || + dists_nanoflann[i][j] == dists_tree[i][j]); + } + } + + delete nanoflann_search; + delete kdtree_search; +} + +// test with FPFHSignature33 +TEST(PCL, KdTreeNanoflann_features) +{ + using FeatureT = FPFHSignature33; + + // Create shared pointers + pcl::PointCloud::Ptr cloud_source_ptr; + cloud_source_ptr = bun0_cloud.makeShared(); + + // first estimate normals + PointCloud::Ptr normals(new PointCloud); + pcl::NormalEstimation norm_est; + norm_est.setRadiusSearch(0.05); + norm_est.setInputCloud(cloud_source_ptr); + norm_est.compute(*normals); + + // then estimate features + PointCloud::Ptr features_source(new PointCloud); + pcl::FPFHEstimation fpfh_est; + fpfh_est.setRadiusSearch(0.05); + fpfh_est.setInputCloud(cloud_source_ptr); + fpfh_est.setInputNormals(normals); + fpfh_est.compute(*features_source); + + pcl::search::KdTree kdtree; + kdtree.setInputCloud(features_source); + + pcl::search::KdTreeNanoflann kdtree_nanoflann; + kdtree_nanoflann.setInputCloud(features_source); + + pcl::Indices indices, indices_nanoflann; + std::vector dists, dists_nanoflann; + + // test nearestKSearch + ASSERT_TRUE(std::isfinite((*features_source)[10].histogram[0])); + kdtree.nearestKSearch((*features_source)[10], 10, indices, dists); + kdtree_nanoflann.nearestKSearch( + (*features_source)[10], 10, indices_nanoflann, dists_nanoflann); + ASSERT_EQ(indices.size(), indices_nanoflann.size()); + ASSERT_EQ(dists.size(), dists_nanoflann.size()); + ASSERT_EQ(indices.size(), dists.size()); + for (std::size_t i = 0; i < indices.size(); ++i) { + EXPECT_EQ(indices[i], indices_nanoflann[i]); + EXPECT_NEAR(dists[i], dists_nanoflann[i], 1e-4); + } + + ASSERT_TRUE(std::isfinite((*features_source)[99].histogram[0])); + kdtree.nearestKSearch((*features_source)[99], 5, indices, dists); + kdtree_nanoflann.nearestKSearch( + (*features_source)[99], 5, indices_nanoflann, dists_nanoflann); + ASSERT_EQ(indices.size(), indices_nanoflann.size()); + ASSERT_EQ(dists.size(), dists_nanoflann.size()); + ASSERT_EQ(indices.size(), dists.size()); + for (std::size_t i = 0; i < indices.size(); ++i) { + EXPECT_EQ(indices[i], indices_nanoflann[i]); + EXPECT_NEAR(dists[i], dists_nanoflann[i], 1e-4); + } +} + +// test with Narf36, because it has a non-trivial point representation +TEST(PCL, KdTreeNanoflann_Narf36) +{ + using FeatureT = pcl::Narf36; + auto feature_cloud = pcl::make_shared>(); + feature_cloud->resize(1000); + for (auto& feature : *feature_cloud) { + feature.x = 20.0 * rand() / RAND_MAX - 10.0; + feature.y = 20.0 * rand() / RAND_MAX - 10.0; + feature.z = 20.0 * rand() / RAND_MAX - 10.0; + feature.roll = M_PI * rand() / RAND_MAX; + feature.pitch = M_PI * rand() / RAND_MAX; + feature.yaw = M_PI * rand() / RAND_MAX; + for (float& desc : feature.descriptor) { + desc = 2.0 * rand() / RAND_MAX - 1.0; + } + } + pcl::search::KdTree kdtree; + kdtree.setInputCloud(feature_cloud); + + pcl::search::KdTreeNanoflann kdtree_nanoflann; + kdtree_nanoflann.setSortedResults(true); + kdtree_nanoflann.setInputCloud(feature_cloud); + + pcl::Indices indices, indices_nanoflann; + std::vector dists, dists_nanoflann; + + // test nearestKSearch + for (std::size_t j = 0; j < feature_cloud->size(); ++j) { + const int k = static_cast(99.0 * rand() / RAND_MAX + 1); + kdtree.nearestKSearch((*feature_cloud)[j], k, indices, dists); + kdtree_nanoflann.nearestKSearch( + (*feature_cloud)[j], k, indices_nanoflann, dists_nanoflann); + ASSERT_EQ(indices.size(), indices_nanoflann.size()); + ASSERT_EQ(dists.size(), dists_nanoflann.size()); + ASSERT_EQ(indices.size(), dists.size()); + ASSERT_EQ(indices_nanoflann.size(), dists_nanoflann.size()); + for (std::size_t i = 0; i < indices.size(); ++i) { + // sometimes, two neighbors have almost the same distance to the query point, but + // are switched due to limited floating point accuracy. + if ((i + 1) < indices.size() && indices[i] != indices_nanoflann[i] && + indices[i + 1] != indices_nanoflann[i + 1] && + (indices[i] == indices_nanoflann[i + 1] || + indices[i + 1] == indices_nanoflann[i]) && + std::abs(dists[i] - dists_nanoflann[i + 1]) < 1e-4 && + std::abs(dists[i + 1] - dists_nanoflann[i]) < 1e-4) { + std::swap(indices[i], indices[i + 1]); + std::swap(dists[i], dists[i + 1]); + } + } + if (!indices.empty() && indices.back() != indices_nanoflann.back() && + std::abs(dists.back() - dists_nanoflann.back()) < 1e-5 && + std::abs(pcl_tests::squared_point_distance((*feature_cloud)[j], + (*feature_cloud)[indices.back()]) - + pcl_tests::squared_point_distance( + (*feature_cloud)[j], (*feature_cloud)[indices_nanoflann.back()])) < + 1e-5) { + indices_nanoflann.back() = indices.back(); + } + for (std::size_t i = 0; i < indices.size(); ++i) { + EXPECT_EQ(indices[i], indices_nanoflann[i]); + EXPECT_NEAR(dists[i], dists_nanoflann[i], 1e-4); + } + } + + // test radiusSearch + for (std::size_t i = 0; i < feature_cloud->size(); ++i) { + const float radius = 3.5 + static_cast(rand()) / RAND_MAX; + kdtree.radiusSearch((*feature_cloud)[i], radius, indices, dists); + kdtree_nanoflann.radiusSearch( + (*feature_cloud)[i], radius, indices_nanoflann, dists_nanoflann); + if (indices.size() > indices_nanoflann.size()) { + if (std::abs(pcl_tests::squared_point_distance((*feature_cloud)[i], + (*feature_cloud)[indices.back()]) - + static_cast(radius) * static_cast(radius)) < 1e-5) { + indices.pop_back(); + dists.pop_back(); + } + } + else if (indices.size() < indices_nanoflann.size()) { + if (std::abs( + pcl_tests::squared_point_distance( + (*feature_cloud)[i], (*feature_cloud)[indices_nanoflann.back()]) - + static_cast(radius) * static_cast(radius)) < 1e-5) { + indices_nanoflann.pop_back(); + dists_nanoflann.pop_back(); + } + } + ASSERT_EQ(indices.size(), indices_nanoflann.size()); + ASSERT_EQ(dists.size(), dists_nanoflann.size()); + ASSERT_EQ(indices.size(), dists.size()); + ASSERT_EQ(indices_nanoflann.size(), dists_nanoflann.size()); + for (std::size_t i = 0; + i < std::min(indices.size(), indices_nanoflann.size()); + ++i) { + // sometimes, two neighbors have almost the same distance to the query point, but + // are switched to due limited floating point accuracy. + if ((i + 1) < indices.size() && indices[i] != indices_nanoflann[i] && + indices[i + 1] != indices_nanoflann[i + 1] && + indices[i] == indices_nanoflann[i + 1] && + indices[i + 1] == indices_nanoflann[i] && + std::abs(dists[i] - dists_nanoflann[i + 1]) < 1e-4 && + std::abs(dists[i + 1] - dists_nanoflann[i]) < 1e-4) { + std::swap(indices[i], indices[i + 1]); + std::swap(dists[i], dists[i + 1]); + } + EXPECT_EQ(indices[i], indices_nanoflann[i]) + << "i=" << i << ", dists[i]=" << dists[i] + << ", dists_nanoflann[i]=" << dists_nanoflann[i] << std::endl; + ; + EXPECT_NEAR(dists[i], dists_nanoflann[i], 1e-4); + } + } +} + +template +double +manhattanDistance(const PointT& a, const PointT& b) +{ + return std::abs(static_cast(a.x) - static_cast(b.x)) + + std::abs(static_cast(a.y) - static_cast(b.y)) + + std::abs(static_cast(a.z) - static_cast(b.z)); +} + +// test with L1/manhattan distance instead of L2/euclidean distance +TEST(PCL, KdTreeNanoflann_nearestKSearch_L1) +{ + pcl::search::KdTreeNanoflann kdtree_nanoflann; + kdtree_nanoflann.setInputCloud(bun0_cloud.makeShared()); + + kdtree_nanoflann.setSortedResults(true); + PointXYZ test_point = bun0_cloud[rand() % bun0_cloud.size()]; + const unsigned int no_of_neighbors = 20; + std::multimap sorted_brute_force_result; + for (std::size_t i = 0; i < bun0_cloud.size(); ++i) { + auto distance = manhattanDistance(bun0_cloud[i], test_point); + sorted_brute_force_result.emplace(distance, i); + } + + pcl::Indices k_indices; + std::vector k_distances; + + EXPECT_EQ(no_of_neighbors, + kdtree_nanoflann.nearestKSearch( + test_point, no_of_neighbors, k_indices, k_distances)); + EXPECT_EQ(k_indices.size(), no_of_neighbors); + EXPECT_EQ(k_distances.size(), no_of_neighbors); + unsigned int counter = 0; + for (auto it = sorted_brute_force_result.begin(); + it != sorted_brute_force_result.end() && counter < no_of_neighbors; + ++it, ++counter) { + EXPECT_EQ(k_indices[counter], it->second); + EXPECT_NEAR(k_distances[counter], it->first, 1e-6); + } + + // test radius search + const float search_radius = 10 * std::next(sorted_brute_force_result.begin())->first; + kdtree_nanoflann.radiusSearch(test_point, search_radius, k_indices, k_distances); + EXPECT_EQ(k_indices.size(), k_distances.size()); + counter = 0; + for (auto it = sorted_brute_force_result.begin(); + it != sorted_brute_force_result.end() && it->first <= search_radius; + ++it, ++counter) { + // sometimes, two neighbors have almost the same distance to the query point, but + // are switched to due limited floating point accuracy. + if ((counter + 1) < k_indices.size() && k_indices[counter] != it->second && + k_indices[counter + 1] != std::next(it)->second && + k_indices[counter] == std::next(it)->second && + k_indices[counter + 1] == it->second && + std::abs(k_distances[counter] - std::next(it)->first) < 1e-6 && + std::abs(k_distances[counter + 1] - it->first) < 1e-6) { + std::swap(k_indices[counter], k_indices[counter + 1]); + std::swap(k_distances[counter], k_distances[counter + 1]); + } + EXPECT_EQ(k_indices[counter], it->second); + EXPECT_NEAR(k_distances[counter], it->first, 1e-6); + } + EXPECT_EQ(k_indices.size(), counter); + // test unsorted radius search + kdtree_nanoflann.setSortedResults(false); + k_indices.clear(); + k_distances.clear(); + kdtree_nanoflann.radiusSearch(test_point, search_radius, k_indices, k_distances); + EXPECT_EQ(k_indices.size(), k_distances.size()); + for (auto it = sorted_brute_force_result.begin(); + it != sorted_brute_force_result.end() && it->first <= search_radius; + ++it) { + auto pos = std::find(k_indices.begin(), k_indices.end(), it->second); + ASSERT_NE(pos, k_indices.end()); // must be found + EXPECT_NEAR(it->first, k_distances[std::distance(k_indices.begin(), pos)], 1e-6); + } +} + +struct MyPoint : public PointXYZ { + MyPoint(float x, float y, float z) + { + this->x = x; + this->y = y; + this->z = z; + } +}; + +class MyPointRepresentationXY : public PointRepresentation { +public: + MyPointRepresentationXY() { this->nr_dimensions_ = 2; } + + void + copyToFloatArray(const MyPoint& p, float* out) const override + { + out[0] = p.x; + out[1] = p.y; + } +}; + +TEST(PCL, KdTreeNanoflann_setPointRepresentation) +{ + PointCloud::Ptr random_cloud(new PointCloud()); + random_cloud->points.emplace_back(86.6f, 42.1f, 92.4f); + random_cloud->points.emplace_back(63.1f, 18.4f, 22.3f); + random_cloud->points.emplace_back(35.5f, 72.5f, 37.3f); + random_cloud->points.emplace_back(99.7f, 37.0f, 8.7f); + random_cloud->points.emplace_back(22.4f, 84.1f, 64.0f); + random_cloud->points.emplace_back(65.2f, 73.4f, 18.0f); + random_cloud->points.emplace_back(60.4f, 57.1f, 4.5f); + random_cloud->points.emplace_back(38.7f, 17.6f, 72.3f); + random_cloud->points.emplace_back(14.2f, 95.7f, 34.7f); + random_cloud->points.emplace_back(2.5f, 26.5f, 66.0f); + + auto kdtree = pcl::make_shared>(); + kdtree->setInputCloud(random_cloud); + EXPECT_EQ(3, kdtree->getPointRepresentation()->getNumberOfDimensions()); + MyPoint p(50.0f, 50.0f, 50.0f); + + // Find k nearest neighbors + constexpr int k = 10; + pcl::Indices k_indices(k); + std::vector k_distances(k); + kdtree->nearestKSearch(p, k, k_indices, k_distances); + for (int i = 0; i < k; ++i) { + // Compare to ground truth values, computed independently + static const int gt_indices[10] = {2, 7, 5, 1, 4, 6, 9, 0, 8, 3}; + static const float gt_distances[10] = {877.8f, + 1674.7f, + 1802.6f, + 1937.5f, + 2120.6f, + 2228.8f, + 3064.5f, + 3199.7f, + 3604.2f, + 4344.8f}; + EXPECT_EQ(k_indices[i], gt_indices[i]); + EXPECT_NEAR(k_distances[i], gt_distances[i], 0.1); + } + + // Find k nearest neighbors with a different point representation + pcl::search::KdTreeNanoflann::PointRepresentationConstPtr ptrep( + new MyPointRepresentationXY); + kdtree->setPointRepresentation(ptrep); + EXPECT_EQ(2, kdtree->getPointRepresentation()->getNumberOfDimensions()); + kdtree->nearestKSearch(p, k, k_indices, k_distances); + for (int i = 0; i < k; ++i) { + // Compare to ground truth values, computed independently + static const int gt_indices[10] = {6, 2, 5, 1, 7, 0, 4, 3, 9, 8}; + static const float gt_distances[10] = {158.6f, + 716.5f, + 778.6f, + 1170.2f, + 1177.5f, + 1402.0f, + 1924.6f, + 2639.1f, + 2808.5f, + 3370.1f}; + EXPECT_EQ(k_indices[i], gt_indices[i]); + EXPECT_NEAR(k_distances[i], gt_distances[i], 0.1); + } + + // Go back to the default, this time with the values rescaled + DefaultPointRepresentation point_rep; + float alpha[3] = {1.0f, 2.0f, 3.0f}; + point_rep.setRescaleValues(alpha); + kdtree->setPointRepresentation(point_rep.makeShared()); + EXPECT_EQ(3, kdtree->getPointRepresentation()->getNumberOfDimensions()); + kdtree->nearestKSearch(p, k, k_indices, k_distances); + for (int i = 0; i < k; ++i) { + // Compare to ground truth values, computed independently + static const int gt_indices[10] = {2, 9, 4, 7, 1, 5, 8, 0, 3, 6}; + static const float gt_distances[10] = {3686.9f, + 6769.2f, + 7177.0f, + 8802.3f, + 11071.5f, + 11637.3f, + 11742.4f, + 17769.0f, + 18497.3f, + 18942.0f}; + EXPECT_EQ(k_indices[i], gt_indices[i]); + EXPECT_NEAR(k_distances[i], gt_distances[i], 0.1); + } +} + +// test with nanoflann::KDTreeSingleIndexDynamicAdaptor (allows to dynamically +// add/remove points) +TEST(PCL, KdTreeNanoflann_dynamic) +{ + using Distance = pcl::search::L2_Simple_Adaptor; + constexpr std::int32_t Dim = 3; + pcl::search::KdTreeNanoflann, + Dim, + pcl::index_t>> + kdtree_nanoflann; + kdtree_nanoflann.setSortedResults(true); + auto input_cloud = bun0_cloud.makeShared(); + input_cloud->reserve(input_cloud->size() + 1); // reserve space for one more point + kdtree_nanoflann.setInputCloud(input_cloud); + + pcl::PointXYZ test_point = (*input_cloud)[rand() % input_cloud->size()]; + const unsigned int no_of_neighbors = 20; + std::multimap sorted_brute_force_result; + for (std::size_t i = 0; i < input_cloud->size(); ++i) { + auto distance = squaredEuclideanDistance((*input_cloud)[i], test_point); + sorted_brute_force_result.emplace(distance, i); + } + + pcl::Indices k_indices; + std::vector k_distances; + + EXPECT_EQ(no_of_neighbors, + kdtree_nanoflann.nearestKSearch( + test_point, no_of_neighbors, k_indices, k_distances)); + EXPECT_EQ(k_indices.size(), no_of_neighbors); + EXPECT_EQ(k_distances.size(), no_of_neighbors); + unsigned int counter = 0; + for (auto it = sorted_brute_force_result.begin(); + it != sorted_brute_force_result.end() && counter < no_of_neighbors; + ++it, ++counter) { + EXPECT_EQ(k_indices[counter], it->second); + EXPECT_NEAR(k_distances[counter], it->first, 1e-6); + } + + kdtree_nanoflann.getNanoflannTree()->removePoint(k_indices[0]); + input_cloud->push_back(test_point); + kdtree_nanoflann.getNanoflannTree()->addPoints(input_cloud->size() - 1, + input_cloud->size() - 1); + sorted_brute_force_result.erase(sorted_brute_force_result.begin()); + sorted_brute_force_result.emplace(0.0, input_cloud->size() - 1); + + EXPECT_EQ(no_of_neighbors, + kdtree_nanoflann.nearestKSearch( + test_point, no_of_neighbors, k_indices, k_distances)); + EXPECT_EQ(k_indices.size(), no_of_neighbors); + EXPECT_EQ(k_distances.size(), no_of_neighbors); + counter = 0; + for (auto it = sorted_brute_force_result.begin(); + it != sorted_brute_force_result.end() && counter < no_of_neighbors; + ++it, ++counter) { + EXPECT_EQ(k_indices[counter], it->second); + EXPECT_NEAR(k_distances[counter], it->first, 1e-6); + } +} + +int +main(int argc, char** argv) +{ + const auto seed = time(nullptr); + std::cout << "seed=" << seed << std::endl; + srand(seed); + testing::InitGoogleTest(&argc, argv); + init(); + + if (argc < 2 || pcl::io::loadPCDFile(argv[1], bun0_cloud) < 0) { + std::cerr << "Failed to read test file. Please download `bun0.pcd` and pass its " + "path to the test." + << std::endl; + return (-1); + } + + return (RUN_ALL_TESTS()); +} diff --git a/test/search/test_search.cpp b/test/search/test_search.cpp index 94b86d76..602e64b2 100644 --- a/test/search/test_search.cpp +++ b/test/search/test_search.cpp @@ -42,6 +42,7 @@ #include #include #include +#include #include #include #include @@ -118,6 +119,10 @@ pcl::search::KdTree KDTree; /** \brief instance of FlannSearch search method to be tested*/ pcl::search::FlannSearch FlannSearch; +#if PCL_HAS_NANOFLANN +pcl::search::KdTreeNanoflann KDTreeNanoflann; +#endif + /** \brief instance of Octree search method to be tested*/ pcl::search::Octree octree_search (0.1); @@ -656,17 +661,26 @@ main (int argc, char** argv) brute_force.setSortedResults (true); KDTree.setSortedResults (true); +#if PCL_HAS_NANOFLANN + KDTreeNanoflann.setSortedResults (true); +#endif octree_search.setSortedResults (true); organized.setSortedResults (true); unorganized_search_methods.push_back (&brute_force); unorganized_search_methods.push_back (&KDTree); unorganized_search_methods.push_back (&FlannSearch); +#if PCL_HAS_NANOFLANN + unorganized_search_methods.push_back (&KDTreeNanoflann); +#endif unorganized_search_methods.push_back (&octree_search); organized_search_methods.push_back (&brute_force); organized_search_methods.push_back (&KDTree); organized_search_methods.push_back (&FlannSearch); +#if PCL_HAS_NANOFLANN + organized_search_methods.push_back (&KDTreeNanoflann); +#endif organized_search_methods.push_back (&octree_search); organized_search_methods.push_back (&organized); diff --git a/tools/obj_rec_ransac_accepted_hypotheses.cpp b/tools/obj_rec_ransac_accepted_hypotheses.cpp index f75bd66a..f884cd9c 100644 --- a/tools/obj_rec_ransac_accepted_hypotheses.cpp +++ b/tools/obj_rec_ransac_accepted_hypotheses.cpp @@ -58,6 +58,7 @@ #include #include #include +#include #include #include #include diff --git a/tools/obj_rec_ransac_hash_table.cpp b/tools/obj_rec_ransac_hash_table.cpp index bde3d941..88b95994 100644 --- a/tools/obj_rec_ransac_hash_table.cpp +++ b/tools/obj_rec_ransac_hash_table.cpp @@ -53,6 +53,7 @@ #include #include #include +#include #include #include diff --git a/tools/obj_rec_ransac_model_opps.cpp b/tools/obj_rec_ransac_model_opps.cpp index d82cbfb1..e6b27a67 100644 --- a/tools/obj_rec_ransac_model_opps.cpp +++ b/tools/obj_rec_ransac_model_opps.cpp @@ -52,6 +52,7 @@ #include #include #include +#include #include #include diff --git a/tools/obj_rec_ransac_orr_octree.cpp b/tools/obj_rec_ransac_orr_octree.cpp index c21a193c..6f55c091 100644 --- a/tools/obj_rec_ransac_orr_octree.cpp +++ b/tools/obj_rec_ransac_orr_octree.cpp @@ -63,6 +63,7 @@ #include #include #include +#include #include #include #include diff --git a/tools/obj_rec_ransac_orr_octree_zprojection.cpp b/tools/obj_rec_ransac_orr_octree_zprojection.cpp index 446d5351..42204cfc 100644 --- a/tools/obj_rec_ransac_orr_octree_zprojection.cpp +++ b/tools/obj_rec_ransac_orr_octree_zprojection.cpp @@ -62,6 +62,7 @@ #include #include #include +#include #include #include #include diff --git a/tools/obj_rec_ransac_result.cpp b/tools/obj_rec_ransac_result.cpp index 884dea61..78b54eb7 100644 --- a/tools/obj_rec_ransac_result.cpp +++ b/tools/obj_rec_ransac_result.cpp @@ -57,6 +57,7 @@ #include #include #include +#include #include #include #include diff --git a/tools/obj_rec_ransac_scene_opps.cpp b/tools/obj_rec_ransac_scene_opps.cpp index 70ddfe42..a1d5099a 100644 --- a/tools/obj_rec_ransac_scene_opps.cpp +++ b/tools/obj_rec_ransac_scene_opps.cpp @@ -53,6 +53,7 @@ #include #include #include +#include #include #include diff --git a/tools/sac_segmentation_plane.cpp b/tools/sac_segmentation_plane.cpp index 6508352d..f443c6b5 100644 --- a/tools/sac_segmentation_plane.cpp +++ b/tools/sac_segmentation_plane.cpp @@ -109,11 +109,9 @@ compute (const pcl::PCLPointCloud2::ConstPtr &input, pcl::PCLPointCloud2 &output RandomSampleConsensus sac (model, threshold); sac.setMaxIterations (max_iterations); bool res = sac.computeModel (); - - pcl::Indices inliers; - sac.getInliers (inliers); - Eigen::VectorXf coefficients; - sac.getModelCoefficients (coefficients); + + auto inliers = sac.getInliers (); + Eigen::VectorXf coefficients = sac.getModelCoefficients (); if (!res || inliers.empty ()) { @@ -121,8 +119,8 @@ compute (const pcl::PCLPointCloud2::ConstPtr &input, pcl::PCLPointCloud2 &output return; } sac.refineModel (2, 50); - sac.getInliers (inliers); - sac.getModelCoefficients (coefficients); + inliers = sac.getInliers (); + coefficients = sac.getModelCoefficients (); print_info ("[done, "); print_value ("%g", tt.toc ()); print_info (" ms, plane has : "); print_value ("%lu", inliers.size ()); print_info (" points]\n"); diff --git a/visualization/include/pcl/visualization/impl/registration_visualizer.hpp b/visualization/include/pcl/visualization/impl/registration_visualizer.hpp index 884735e4..4a40b11f 100644 --- a/visualization/include/pcl/visualization/impl/registration_visualizer.hpp +++ b/visualization/include/pcl/visualization/impl/registration_visualizer.hpp @@ -38,6 +38,7 @@ #pragma once +#include #include diff --git a/visualization/include/pcl/visualization/interactor_style.h b/visualization/include/pcl/visualization/interactor_style.h index 823235e0..412f4d45 100644 --- a/visualization/include/pcl/visualization/interactor_style.h +++ b/visualization/include/pcl/visualization/interactor_style.h @@ -118,7 +118,7 @@ namespace pcl ~PCLVisualizerInteractorStyle () override = default; // this macro defines Superclass, the isA functionality and the safe downcast method - vtkTypeMacro (PCLVisualizerInteractorStyle, vtkInteractorStyleRubberBandPick); + vtkTypeMacro (PCLVisualizerInteractorStyle, vtkInteractorStyleRubberBandPick) /** \brief Initialization routine. Must be called before anything else. */ virtual void diff --git a/visualization/src/common/common.cpp b/visualization/src/common/common.cpp index 92932334..2eeb72e3 100644 --- a/visualization/src/common/common.cpp +++ b/visualization/src/common/common.cpp @@ -533,7 +533,7 @@ pcl::visualization::Camera::computeViewMatrix (Eigen::Matrix4d &view_mat) const view_mat.block <1, 3> (2, 0) = -zAxis; view_mat.row (3) << 0, 0, 0, 1; - view_mat.block <3, 1> (0, 3) = view_mat.topLeftCorner<3, 3> () * (-posv); + view_mat.block <3, 1> (0, 3).noalias() = view_mat.topLeftCorner<3, 3> () * (-posv); } /////////////////////////////////////////////////////////////////////// diff --git a/visualization/src/histogram_visualizer.cpp b/visualization/src/histogram_visualizer.cpp index 7fbeab14..3be17dd8 100644 --- a/visualization/src/histogram_visualizer.cpp +++ b/visualization/src/histogram_visualizer.cpp @@ -184,7 +184,7 @@ pcl::visualization::PCLHistogramVisualizer::reCreateActor ( field_data->SetFieldData (field_values); renwinupd->xy_plot_->AddDataObjectInput (field_data); - renwinupd->ren_->AddActor2D (renwinupd->xy_plot_); + renwinupd->ren_->AddViewProp (renwinupd->xy_plot_); renwinupd->xy_plot_->SetYTitle (""); renwinupd->xy_plot_->SetXTitle (""); renwinupd->xy_plot_->SetYRange (min_max[0], min_max[1]); @@ -248,7 +248,7 @@ pcl::visualization::PCLHistogramVisualizer::createActor ( renwinint.xy_plot_->SetWidth (1); renwinint.xy_plot_->SetHeight (1); // Create the new window with its interactor and renderer - renwinint.ren_->AddActor2D (renwinint.xy_plot_); + renwinint.ren_->AddViewProp (renwinint.xy_plot_); renwinint.ren_->SetBackground (1, 1, 1); renwinint.win_->SetWindowName (id.c_str ()); renwinint.win_->AddRenderer (renwinint.ren_); diff --git a/visualization/src/point_picking_event.cpp b/visualization/src/point_picking_event.cpp index aae888cb..5613eb2a 100644 --- a/visualization/src/point_picking_event.cpp +++ b/visualization/src/point_picking_event.cpp @@ -66,7 +66,7 @@ pcl::visualization::PointPickingCallback::Execute (vtkObject *caller, unsigned l if ((eventid == vtkCommand::LeftButtonPressEvent) && (iren->GetShiftKey () > 0)) { float x = 0, y = 0, z = 0; - int idx = performSinglePick (iren, x, y, z); + const auto idx = performSinglePick (iren, x, y, z); // Create a PointPickingEvent if a point was selected if (idx != pcl::UNAVAILABLE) {